]> git.sur5r.net Git - openldap/blob - servers/slapd/result.c
adaf3c0ab33f49740484c3dff0d2cdf93eee43dd
[openldap] / servers / slapd / result.c
1 /* result.c - routines to send ldap results, errors, and referrals */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/socket.h>
13 #include <ac/errno.h>
14 #include <ac/string.h>
15 #include <ac/ctype.h>
16 #include <ac/time.h>
17 #include <ac/unistd.h>
18
19 #include "slap.h"
20
21 #ifdef LDAP_SLAPI
22 #include "slapi.h"
23 #endif
24
25 static char *v2ref( BerVarray ref, const char *text )
26 {
27         size_t len = 0, i = 0;
28         char *v2;
29
30         if(ref == NULL) {
31                 if (text) {
32                         return ch_strdup(text);
33                 } else {
34                         return NULL;
35                 }
36         }
37         
38         if ( text != NULL ) {
39                 len = strlen( text );
40                 if (text[len-1] != '\n') {
41                     i = 1;
42                 }
43         }
44
45         v2 = SLAP_MALLOC( len+i+sizeof("Referral:") );
46         if( v2 == NULL ) {
47 #ifdef NEW_LOGGING
48                 LDAP_LOG( OPERATION, ERR, "v2ref: SLAP_MALLOC failed", 0, 0, 0 );
49 #else
50                 Debug( LDAP_DEBUG_ANY, "v2ref: SLAP_MALLOC failed", 0, 0, 0 );
51 #endif
52                 return NULL;
53         }
54
55         if( text != NULL ) {
56                 strcpy(v2, text);
57                 if( i ) {
58                         v2[len++] = '\n';
59                 }
60         }
61         strcpy( v2+len, "Referral:" );
62         len += sizeof("Referral:");
63
64         for( i=0; ref[i].bv_val != NULL; i++ ) {
65                 v2 = SLAP_REALLOC( v2, len + ref[i].bv_len + 1 );
66                 if( v2 == NULL ) {
67 #ifdef NEW_LOGGING
68                         LDAP_LOG( OPERATION, ERR, "v2ref: SLAP_MALLOC failed", 0, 0, 0 );
69 #else
70                         Debug( LDAP_DEBUG_ANY, "v2ref: SLAP_MALLOC failed", 0, 0, 0 );
71 #endif
72                         return NULL;
73                 }
74                 v2[len-1] = '\n';
75                 AC_MEMCPY(&v2[len], ref[i].bv_val, ref[i].bv_len );
76                 len += ref[i].bv_len;
77                 if (ref[i].bv_val[ref[i].bv_len-1] != '/') {
78                         ++len;
79                 }
80         }
81
82         v2[len-1] = '\0';
83         return v2;
84 }
85
86 static ber_tag_t req2res( ber_tag_t tag )
87 {
88         switch( tag ) {
89         case LDAP_REQ_ADD:
90         case LDAP_REQ_BIND:
91         case LDAP_REQ_COMPARE:
92         case LDAP_REQ_EXTENDED:
93         case LDAP_REQ_MODIFY:
94         case LDAP_REQ_MODRDN:
95                 tag++;
96                 break;
97
98         case LDAP_REQ_DELETE:
99                 tag = LDAP_RES_DELETE;
100                 break;
101
102         case LDAP_REQ_ABANDON:
103         case LDAP_REQ_UNBIND:
104                 tag = LBER_SEQUENCE;
105                 break;
106
107         case LDAP_REQ_SEARCH:
108                 tag = LDAP_RES_SEARCH_RESULT;
109                 break;
110
111         default:
112                 tag = LBER_SEQUENCE;
113         }
114
115         return tag;
116 }
117
118 static long send_ldap_ber(
119         Connection *conn,
120         BerElement *ber )
121 {
122         ber_len_t bytes;
123
124         ber_get_option( ber, LBER_OPT_BER_BYTES_TO_WRITE, &bytes );
125
126         /* write only one pdu at a time - wait til it's our turn */
127         ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
128
129         /* lock the connection */ 
130         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
131
132         /* write the pdu */
133         while( 1 ) {
134                 int err;
135                 ber_socket_t    sd;
136
137                 if ( connection_state_closing( conn ) ) {
138                         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
139                         ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
140
141                         return 0;
142                 }
143
144                 if ( ber_flush( conn->c_sb, ber, 0 ) == 0 ) {
145                         break;
146                 }
147
148                 err = errno;
149
150                 /*
151                  * we got an error.  if it's ewouldblock, we need to
152                  * wait on the socket being writable.  otherwise, figure
153                  * it's a hard error and return.
154                  */
155
156 #ifdef NEW_LOGGING
157                 LDAP_LOG( OPERATION, ERR, 
158                         "send_ldap_ber: conn %lu  ber_flush failed err=%d (%s)\n",
159                         conn ? conn->c_connid : 0, err, sock_errstr(err) );
160 #else
161                 Debug( LDAP_DEBUG_CONNS, "ber_flush failed errno=%d reason=\"%s\"\n",
162                     err, sock_errstr(err), 0 );
163 #endif
164
165                 if ( err != EWOULDBLOCK && err != EAGAIN ) {
166                         connection_closing( conn );
167
168                         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
169                         ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
170
171                         return( -1 );
172                 }
173
174                 /* wait for socket to be write-ready */
175                 conn->c_writewaiter = 1;
176                 ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
177                 slapd_set_write( sd, 1 );
178
179                 ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
180                 conn->c_writewaiter = 0;
181         }
182
183         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
184         ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
185
186         return bytes;
187 }
188
189 static int
190 send_ldap_controls( BerElement *ber, LDAPControl **c )
191 {
192         int rc;
193         if( c == NULL ) return 0;
194
195         rc = ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS );
196         if( rc == -1 ) return rc;
197
198         for( ; *c != NULL; c++) {
199                 rc = ber_printf( ber, "{s" /*}*/, (*c)->ldctl_oid );
200
201                 if( (*c)->ldctl_iscritical ) {
202                         rc = ber_printf( ber, "b",
203                                 (ber_int_t) (*c)->ldctl_iscritical ) ;
204                         if( rc == -1 ) return rc;
205                 }
206
207                 if( (*c)->ldctl_value.bv_val != NULL ) {
208                         rc = ber_printf( ber, "O", &((*c)->ldctl_value)); 
209                         if( rc == -1 ) return rc;
210                 }
211
212                 rc = ber_printf( ber, /*{*/"N}" );
213                 if( rc == -1 ) return rc;
214         }
215
216         rc = ber_printf( ber, /*{*/"N}" );
217
218         return rc;
219 }
220
221 static void
222 send_ldap_response(
223         Operation *op,
224         SlapReply *rs )
225 {
226         char berbuf[LBER_ELEMENT_SIZEOF];
227         BerElement      *ber = (BerElement *)berbuf;
228         int             rc;
229         long    bytes;
230
231         if (op->o_callback && op->o_callback->sc_response) {
232                 op->o_callback->sc_response( op, rs );
233                 return;
234         }
235                 
236 #ifdef LDAP_CONNECTIONLESS
237         if (op->o_conn && op->o_conn->c_is_udp)
238                 ber = op->o_res_ber;
239         else
240 #endif
241         ber_init_w_nullc( ber, LBER_USE_DER );
242
243 #ifdef NEW_LOGGING
244         LDAP_LOG( OPERATION, ENTRY, 
245                 "send_ldap_response:  msgid=%d tag=%lu err=%d\n",
246                 rs->sr_msgid, rs->sr_tag, rs->sr_err );
247 #else
248         Debug( LDAP_DEBUG_TRACE,
249                 "send_ldap_response: msgid=%d tag=%lu err=%d\n",
250                 rs->sr_msgid, rs->sr_tag, rs->sr_err );
251 #endif
252
253         if( rs->sr_ref ) {
254 #ifdef NEW_LOGGING
255                 LDAP_LOG( OPERATION, ARGS, 
256                         "send_ldap_response: conn %lu  ref=\"%s\"\n",
257                         op->o_connid,
258                         rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL" , 0 );
259 #else
260                 Debug( LDAP_DEBUG_ARGS, "send_ldap_response: ref=\"%s\"\n",
261                         rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL",
262                         NULL, NULL );
263 #endif
264         }
265
266 #ifdef LDAP_CONNECTIONLESS
267         if (op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2) {
268                 rc = ber_printf( ber, "t{ess" /*"}}"*/,
269                         rs->sr_tag, rs->sr_err,
270                 rs->sr_matched == NULL ? "" : rs->sr_matched,
271                 rs->sr_text == NULL ? "" : rs->sr_text );
272         } else 
273 #endif
274         {
275             rc = ber_printf( ber, "{it{ess" /*"}}"*/,
276                 rs->sr_msgid, rs->sr_tag, rs->sr_err,
277                 rs->sr_matched == NULL ? "" : rs->sr_matched,
278                 rs->sr_text == NULL ? "" : rs->sr_text );
279         }
280
281         if( rc != -1 ) {
282                 if ( rs->sr_ref != NULL ) {
283                         assert( rs->sr_err == LDAP_REFERRAL );
284                         rc = ber_printf( ber, "t{W}",
285                                 LDAP_TAG_REFERRAL, rs->sr_ref );
286                 } else {
287                         assert( rs->sr_err != LDAP_REFERRAL );
288                 }
289         }
290
291         if( rc != -1 && rs->sr_type == REP_SASL && rs->sr_sasldata != NULL ) {
292                 rc = ber_printf( ber, "tO",
293                         LDAP_TAG_SASL_RES_CREDS, rs->sr_sasldata );
294         }
295
296         if( rc != -1 && rs->sr_type == REP_EXTENDED ) {
297                 if ( rs->sr_rspoid != NULL ) {
298                         rc = ber_printf( ber, "ts",
299                                 LDAP_TAG_EXOP_RES_OID, rs->sr_rspoid );
300                 }
301                 if( rc != -1 && rs->sr_rspdata != NULL ) {
302                         rc = ber_printf( ber, "tO",
303                                 LDAP_TAG_EXOP_RES_VALUE, rs->sr_rspdata );
304                 }
305         }
306
307         if( rc != -1 ) {
308                 rc = ber_printf( ber, /*"{"*/ "N}" );
309         }
310
311         if( rc != -1 && rs->sr_ctrls != NULL ) {
312                 rc = send_ldap_controls( ber, rs->sr_ctrls );
313         }
314
315         if( rc != -1 ) {
316                 rc = ber_printf( ber, /*"{"*/ "N}" );
317         }
318
319 #ifdef LDAP_CONNECTIONLESS
320         if( op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2 && rc != -1 ) {
321                 rc = ber_printf( ber, /*"{"*/ "N}" );
322         }
323 #endif
324                 
325         if ( rc == -1 ) {
326 #ifdef NEW_LOGGING
327                 LDAP_LOG( OPERATION, ERR, 
328                         "send_ldap_response: conn %lu  ber_printf failed\n",
329                         op->o_connid, 0, 0 );
330 #else
331                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
332 #endif
333
334 #ifdef LDAP_CONNECTIONLESS
335                 if (!op->o_conn || op->o_conn->c_is_udp == 0)
336 #endif
337                 ber_free_buf( ber );
338                 return;
339         }
340
341         /* send BER */
342         bytes = send_ldap_ber( op->o_conn, ber );
343 #ifdef LDAP_CONNECTIONLESS
344         if (!op->o_conn || op->o_conn->c_is_udp == 0)
345 #endif
346         ber_free_buf( ber );
347
348         if ( bytes < 0 ) {
349 #ifdef NEW_LOGGING
350                 LDAP_LOG( OPERATION, ERR, 
351                         "send_ldap_response: conn %lu ber write failed\n",
352                         op->o_connid : 0, 0, 0 );
353 #else
354                 Debug( LDAP_DEBUG_ANY,
355                         "send_ldap_response: ber write failed\n",
356                         0, 0, 0 );
357 #endif
358
359                 return;
360         }
361
362 #ifdef LDAP_SLAPI
363         slapi_pblock_set( op->o_pb, SLAPI_RESULT_CODE, (void *)rs->sr_err );
364         slapi_pblock_set( op->o_pb, SLAPI_RESULT_MATCHED, ( rs->sr_matched != NULL ) ? (void *)ch_strdup( rs->sr_matched ) : NULL );
365         slapi_pblock_set( op->o_pb, SLAPI_RESULT_TEXT, ( rs->sr_text != NULL ) ? (void *)ch_strdup( rs->sr_text ) : NULL );
366 #endif /* LDAP_SLAPI */
367
368         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
369         num_bytes_sent += bytes;
370         num_pdu_sent++;
371         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
372         return;
373 }
374
375
376 void
377 send_ldap_disconnect( Operation *op, SlapReply *rs )
378 {
379 #define LDAP_UNSOLICITED_ERROR(e) \
380         (  (e) == LDAP_PROTOCOL_ERROR \
381         || (e) == LDAP_STRONG_AUTH_REQUIRED \
382         || (e) == LDAP_UNAVAILABLE )
383
384         assert( LDAP_UNSOLICITED_ERROR( rs->sr_err ) );
385
386         rs->sr_type = REP_EXTENDED;
387
388 #ifdef NEW_LOGGING
389         LDAP_LOG( OPERATION, ENTRY, 
390                 "send_ldap_disconnect: conn %lu  %d:%s\n",
391                 op->o_connid, rs->sr_err, rs->sr_text ? rs->sr_text : "" );
392 #else
393         Debug( LDAP_DEBUG_TRACE,
394                 "send_ldap_disconnect %d:%s\n",
395                 rs->sr_err, rs->sr_text ? rs->sr_text : "", NULL );
396 #endif
397
398
399         if ( op->o_protocol < LDAP_VERSION3 ) {
400                 rs->sr_rspoid = NULL;
401                 rs->sr_tag = req2res( op->o_tag );
402                 rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
403
404         } else {
405                 rs->sr_rspoid = LDAP_NOTICE_DISCONNECT;
406                 rs->sr_tag = LDAP_RES_EXTENDED;
407                 rs->sr_msgid = 0;
408         }
409
410         send_ldap_response( op, rs );
411
412         Statslog( LDAP_DEBUG_STATS,
413             "conn=%lu op=%lu DISCONNECT tag=%lu err=%d text=%s\n",
414                 op->o_connid, op->o_opid, rs->sr_tag, rs->sr_err, rs->sr_text ? rs->sr_text : "" );
415 }
416
417 void
418 slap_send_ldap_result( Operation *op, SlapReply *rs )
419 {
420         char *tmp = NULL;
421         const char *otext = rs->sr_text;
422         BerVarray oref = rs->sr_ref;
423
424         assert( !LDAP_API_ERROR( rs->sr_err ) );
425
426 #ifdef NEW_LOGGING
427         LDAP_LOG( OPERATION, ENTRY, 
428                 "send_ldap_result: conn %lu op=%lu p=%d\n",
429                 op->o_connid, op->o_opid, op->o_protocol );
430 #else
431         Debug( LDAP_DEBUG_TRACE,
432                 "send_ldap_result: conn=%lu op=%lu p=%d\n",
433                 op->o_connid, op->o_opid, op->o_protocol );
434 #endif
435
436 #ifdef NEW_LOGGING
437         LDAP_LOG( OPERATION, ARGS, 
438                 "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n",
439                 rs->sr_err, rs->sr_matched ? rs->sr_matched : "", rs->sr_text ? rs->sr_text : "" );
440 #else
441         Debug( LDAP_DEBUG_ARGS,
442                 "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n",
443                 rs->sr_err, rs->sr_matched ? rs->sr_matched : "", rs->sr_text ? rs->sr_text : "" );
444 #endif
445
446
447         if( rs->sr_ref ) {
448 #ifdef NEW_LOGGING
449                 LDAP_LOG( OPERATION, ARGS, 
450                         "send_ldap_result: referral=\"%s\"\n",
451                         rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL", 0, 0 );
452 #else
453                 Debug( LDAP_DEBUG_ARGS,
454                         "send_ldap_result: referral=\"%s\"\n",
455                         rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL",
456                         NULL, NULL );
457 #endif
458         }
459
460         assert( rs->sr_err != LDAP_PARTIAL_RESULTS );
461
462         if ( rs->sr_err == LDAP_REFERRAL ) {
463 #ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
464                 if( op->o_domain_scope ) {
465                         rs->sr_ref = NULL;
466                 }
467 #endif
468                 if( rs->sr_ref == NULL ) {
469                         rs->sr_err = LDAP_NO_SUCH_OBJECT;
470                 } else if ( op->o_protocol < LDAP_VERSION3 ) {
471                         rs->sr_err = LDAP_PARTIAL_RESULTS;
472                 }
473         }
474
475         if ( op->o_protocol < LDAP_VERSION3 ) {
476                 tmp = v2ref( rs->sr_ref, rs->sr_text );
477                 rs->sr_text = tmp;
478                 rs->sr_ref = NULL;
479         }
480
481         rs->sr_tag = req2res( op->o_tag );
482         rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
483
484         send_ldap_response( op, rs );
485
486         if ( rs->sr_type == REP_SRESULT ) {
487                 char nbuf[64];
488                 snprintf( nbuf, sizeof nbuf, "%d nentries=%d", rs->sr_err, rs->sr_nentries );
489
490                 Statslog( LDAP_DEBUG_STATS,
491                         "conn=%lu op=%lu SEARCH RESULT tag=%lu err=%s text=%s\n",
492                         op->o_connid, op->o_opid, rs->sr_tag, nbuf, rs->sr_text ? rs->sr_text : "" );
493         } else {
494                 Statslog( LDAP_DEBUG_STATS,
495                         "conn=%lu op=%lu RESULT tag=%lu err=%d text=%s\n",
496                         op->o_connid, op->o_opid, rs->sr_tag, rs->sr_err, rs->sr_text ? rs->sr_text : "" );
497         }
498
499         if( tmp != NULL ) {
500                 ch_free(tmp);
501         }
502         rs->sr_text = otext;
503         rs->sr_ref = oref;
504 }
505
506 void
507 send_ldap_sasl( Operation *op, SlapReply *rs )
508 {
509         rs->sr_type = REP_SASL;
510 #ifdef NEW_LOGGING
511         LDAP_LOG( OPERATION, ENTRY, 
512                 "send_ldap_sasl: conn %lu err=%d len=%lu\n",
513                 op->o_connid, rs->sr_err, rs->sr_sasldata ? rs->sr_sasldata->bv_len : -1 );
514 #else
515         Debug( LDAP_DEBUG_TRACE, "send_ldap_sasl: err=%d len=%ld\n",
516                 rs->sr_err, rs->sr_sasldata ? (long) rs->sr_sasldata->bv_len : -1, NULL );
517 #endif
518
519         rs->sr_tag = req2res( op->o_tag );
520         rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
521
522         send_ldap_response( op, rs );
523 }
524
525 void
526 slap_send_ldap_extended( Operation *op, SlapReply *rs )
527 {
528         rs->sr_type = REP_EXTENDED;
529
530 #ifdef NEW_LOGGING
531         LDAP_LOG( OPERATION, ENTRY, 
532                 "send_ldap_extended: err=%d oid=%s len=%ld\n",
533                 rs->sr_err, rs->sr_rspoid ? rs->sr_rspoid : "",
534                 rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 );
535 #else
536         Debug( LDAP_DEBUG_TRACE,
537                 "send_ldap_extended: err=%d oid=%s len=%ld\n",
538                 rs->sr_err,
539                 rs->sr_rspoid ? rs->sr_rspoid : "",
540                 rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 );
541 #endif
542
543         rs->sr_tag = req2res( op->o_tag );
544         rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
545
546         send_ldap_response( op, rs );
547 }
548
549 #ifdef LDAP_RES_INTERMEDIATE_RESP
550 void
551 slap_send_ldap_intermediate_resp( Operation *op, SlapReply *rs )
552 {
553         rs->sr_type = REP_EXTENDED;
554 #ifdef NEW_LOGGING
555         LDAP_LOG( OPERATION, ENTRY,
556                 "send_ldap_intermediate: err=%d oid=%s len=%ld\n",
557                 rs->sr_err, rs->sr_rspoid ? rs->sr_rspoid : "",
558                 rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 );
559 #else
560         Debug( LDAP_DEBUG_TRACE,
561                 "send_ldap_intermediate: err=%d oid=%s len=%ld\n",
562                 rs->sr_err,
563                 rs->sr_rspoid ? rs->sr_rspoid : "",
564                 rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 );
565 #endif
566         rs->sr_tag = LDAP_RES_INTERMEDIATE_RESP;
567         rs->sr_msgid = op->o_msgid;
568         send_ldap_response( op, rs );
569 }
570 #endif
571
572 void
573 slap_send_search_result( Operation *op, SlapReply *rs )
574 {
575         rs->sr_type = REP_SRESULT;
576         slap_send_ldap_result( op, rs );
577 }
578
579 int
580 slap_send_search_entry( Operation *op, SlapReply *rs )
581 {
582         char berbuf[LBER_ELEMENT_SIZEOF];
583         BerElement      *ber = (BerElement *)berbuf;
584         Attribute       *a, *aa;
585         int             i, j, rc=-1, bytes;
586         char            *edn;
587         int             userattrs;
588         int             opattrs;
589         AccessControlState acl_state = ACL_STATE_INIT;
590 #ifdef LDAP_SLAPI
591         /* Support for computed attribute plugins */
592         computed_attr_context    ctx;
593         AttributeName   *anp;
594 #endif
595
596         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
597
598         /* a_flags: array of flags telling if the i-th element will be
599          *          returned or filtered out
600          * e_flags: array of a_flags
601          */
602         char **e_flags = NULL;
603
604         rs->sr_type = REP_SEARCH;
605         if (op->o_callback && op->o_callback->sc_sendentry) {
606                 return op->o_callback->sc_sendentry( op, rs );
607         }
608
609 #ifdef NEW_LOGGING
610         LDAP_LOG( OPERATION, ENTRY, 
611                 "send_search_entry: conn %lu    dn=\"%s\"%s\n",
612                 op->o_connid, rs->sr_entry->e_name.bv_val, op->ors_attrsonly ? " (attrsOnly)" : "" );
613 #else
614         Debug( LDAP_DEBUG_TRACE,
615                 "=> send_search_entry: dn=\"%s\"%s\n",
616                 rs->sr_entry->e_name.bv_val, op->ors_attrsonly ? " (attrsOnly)" : "", 0 );
617 #endif
618
619         if ( ! access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL ) )
620         {
621 #ifdef NEW_LOGGING
622                 LDAP_LOG( ACL, INFO, 
623                         "send_search_entry: conn %lu access to entry (%s) not allowed\n", 
624                         op->o_connid, rs->sr_entry->e_name.bv_val, 0 );
625 #else
626                 Debug( LDAP_DEBUG_ACL,
627                         "send_search_entry: access to entry not allowed\n",
628                     0, 0, 0 );
629 #endif
630
631                 return( 1 );
632         }
633
634         edn = rs->sr_entry->e_nname.bv_val;
635
636 #ifdef LDAP_CONNECTIONLESS
637         if (op->o_conn && op->o_conn->c_is_udp)
638             ber = op->o_res_ber;
639         else
640 #endif
641         ber_init_w_nullc( ber, LBER_USE_DER );
642
643 #ifdef LDAP_CONNECTIONLESS
644         if (op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2) {
645             rc = ber_printf(ber, "t{O{" /*}}*/,
646                 LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name);
647         } else
648 #endif
649         {
650             rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
651                 LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
652         }
653
654         if ( rc == -1 ) {
655 #ifdef NEW_LOGGING
656                 LDAP_LOG( OPERATION, ERR, 
657                         "send_search_entry: conn %lu  ber_printf failed\n", 
658                         op->o_connid, 0, 0 );
659 #else
660                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
661 #endif
662
663 #ifdef LDAP_CONNECTIONLESS
664                 if (!op->o_conn || op->o_conn->c_is_udp == 0)
665 #endif
666                 ber_free_buf( ber );
667                 send_ldap_error( op, rs, LDAP_OTHER, "encoding DN error" );
668                 goto error_return;
669         }
670
671         /* check for special all user attributes ("*") type */
672         userattrs = ( rs->sr_attrs == NULL ) ? 1
673                 : an_find( rs->sr_attrs, &AllUser );
674
675         /* check for special all operational attributes ("+") type */
676         opattrs = ( rs->sr_attrs == NULL ) ? 0
677                 : an_find( rs->sr_attrs, &AllOper );
678
679         /* create an array of arrays of flags. Each flag corresponds
680          * to particular value of attribute and equals 1 if value matches
681          * to ValuesReturnFilter or 0 if not
682          */     
683         if ( op->vrFilter != NULL ) {
684                 int     k = 0;
685                 size_t  size;
686
687                 for ( a = rs->sr_entry->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
688                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
689                 }
690
691                 size = i * sizeof(char *) + k;
692                 if ( size > 0 ) {
693                         char    *a_flags;
694                         e_flags = SLAP_CALLOC ( 1, i * sizeof(char *) + k );
695                         if( e_flags == NULL ) {
696 #ifdef NEW_LOGGING
697                                 LDAP_LOG( OPERATION, ERR, 
698                                         "send_search_entry: conn %lu SLAP_CALLOC failed\n",
699                                         op->o_connid : 0, 0, 0 );
700 #else
701                         Debug( LDAP_DEBUG_ANY, 
702                                         "send_search_entry: SLAP_CALLOC failed\n", 0, 0, 0 );
703 #endif
704                                 ber_free( ber, 1 );
705         
706                                 send_ldap_error( op, rs, LDAP_OTHER, "out of memory" );
707                                 goto error_return;
708                         }
709                         a_flags = (char *)(e_flags + i);
710                         memset( a_flags, 0, k );
711                         for ( a = rs->sr_entry->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
712                                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
713                                 e_flags[i] = a_flags;
714                                 a_flags += j;
715                         }
716         
717                         rc = filter_matched_values(op, rs->sr_entry->e_attrs, &e_flags) ; 
718                         if ( rc == -1 ) {
719 #ifdef NEW_LOGGING
720                                 LDAP_LOG( OPERATION, ERR, 
721                                         "send_search_entry: conn %lu matched values filtering failed\n",
722                                         op->o_connid : 0, 0, 0 );
723 #else
724                         Debug( LDAP_DEBUG_ANY,
725                                         "matched values filtering failed\n", 0, 0, 0 );
726 #endif
727 #ifdef LDAP_CONNECTIONLESS
728                         if (!op->o_conn || op->o_conn->c_is_udp == 0)
729 #endif
730                                 ber_free( ber, 1 );
731                                 send_ldap_error( op, rs, LDAP_OTHER, "matched values filtering error" );
732                                 goto error_return;
733                         }
734                 }
735         }
736
737         for ( a = rs->sr_entry->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) {
738                 AttributeDescription *desc = a->a_desc;
739
740                 if ( rs->sr_attrs == NULL ) {
741                         /* all attrs request, skip operational attributes */
742                         if( is_at_operational( desc->ad_type ) ) {
743                                 continue;
744                         }
745
746                 } else {
747                         /* specific attrs requested */
748                         if ( is_at_operational( desc->ad_type ) ) {
749                                 if( !opattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
750                                         continue;
751                                 }
752
753                         } else {
754                                 if (!userattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
755                                         continue;
756                                 }
757                         }
758                 }
759
760                 if ( ! access_allowed( op, rs->sr_entry, desc, NULL,
761                         ACL_READ, &acl_state ) )
762                 {
763 #ifdef NEW_LOGGING
764                         LDAP_LOG( ACL, INFO, 
765                                 "send_search_entry: conn %lu  access to attribute %s not "
766                                 "allowed\n", op->o_connid, desc->ad_cname.bv_val, 0 );
767 #else
768                         Debug( LDAP_DEBUG_ACL, "acl: "
769                                 "access to attribute %s not allowed\n",
770                             desc->ad_cname.bv_val, 0, 0 );
771 #endif
772                         continue;
773                 }
774
775                 if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
776 #ifdef NEW_LOGGING
777                         LDAP_LOG( OPERATION, ERR, 
778                                 "send_search_entry: conn %lu  ber_printf failed\n", 
779                                 op->o_connid, 0, 0 );
780 #else
781                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
782 #endif
783
784 #ifdef LDAP_CONNECTIONLESS
785                         if (!op->o_conn || op->o_conn->c_is_udp == 0)
786 #endif
787                         ber_free_buf( ber );
788                         send_ldap_error( op, rs, LDAP_OTHER, "encoding description error");
789                         goto error_return;
790                 }
791
792                 if ( ! op->ors_attrsonly ) {
793                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
794                                 if ( ! access_allowed( op, rs->sr_entry,
795                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
796                                 {
797 #ifdef NEW_LOGGING
798                                         LDAP_LOG( ACL, INFO, 
799                                                 "send_search_entry: conn %lu "
800                                                 "access to attribute %s, value %d not allowed\n",
801                                                 op->o_connid, desc->ad_cname.bv_val, i );
802 #else
803                                         Debug( LDAP_DEBUG_ACL,
804                                                 "acl: access to attribute %s, "
805                                                 "value %d not allowed\n",
806                                                 desc->ad_cname.bv_val, i, 0 );
807 #endif
808
809                                         continue;
810                                 }
811
812                                 if ( op->vrFilter && e_flags[j][i] == 0 ){
813                                         continue;
814                                 }
815
816                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
817 #ifdef NEW_LOGGING
818                                         LDAP_LOG( OPERATION, ERR, 
819                                                 "send_search_entry: conn %lu  "
820                                                 "ber_printf failed.\n", op->o_connid, 0, 0 );
821 #else
822                                         Debug( LDAP_DEBUG_ANY,
823                                             "ber_printf failed\n", 0, 0, 0 );
824 #endif
825
826 #ifdef LDAP_CONNECTIONLESS
827                                         if (!op->o_conn || op->o_conn->c_is_udp == 0)
828 #endif
829                                         ber_free_buf( ber );
830                                         send_ldap_error( op, rs, LDAP_OTHER, "encoding values error" );
831                                         goto error_return;
832                                 }
833                         }
834                 }
835
836                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
837 #ifdef NEW_LOGGING
838                         LDAP_LOG( OPERATION, ERR, 
839                                 "send_search_entry: conn %lu ber_printf failed\n", 
840                                 op->o_connid, 0, 0 );
841 #else
842                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
843 #endif
844
845 #ifdef LDAP_CONNECTIONLESS
846                         if (!op->o_conn || op->o_conn->c_is_udp == 0)
847 #endif
848                         ber_free_buf( ber );
849                         send_ldap_error( op, rs, LDAP_OTHER, "encode end error" );
850                         goto error_return;
851                 }
852         }
853
854         /* eventually will loop through generated operational attributes */
855         /* only have subschemaSubentry implemented */
856         aa = backend_operational( op, rs, opattrs );
857
858         if ( aa != NULL && op->vrFilter != NULL ) {
859                 int     k = 0;
860                 size_t  size;
861
862                 for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
863                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
864                 }
865
866                 size = i * sizeof(char *) + k;
867                 if ( size > 0 ) {
868                         char    *a_flags, **tmp;
869                 
870                         /*
871                          * Reuse previous memory - we likely need less space
872                          * for operational attributes
873                          */
874                         tmp = SLAP_REALLOC ( e_flags, i * sizeof(char *) + k );
875                         if ( tmp == NULL ) {
876 #ifdef NEW_LOGGING
877                                 LDAP_LOG( OPERATION, ERR, 
878                                         "send_search_entry: conn %lu "
879                                         "not enough memory "
880                                         "for matched values filtering\n", 
881                                         op->o_connid, 0, 0);
882 #else
883                                 Debug( LDAP_DEBUG_ANY,
884                                         "send_search_entry: conn %lu "
885                                         "not enough memory "
886                                         "for matched values filtering\n",
887                                         op->o_connid, 0, 0 );
888 #endif
889                                 ber_free( ber, 1 );
890         
891                                 send_ldap_error( op, rs, LDAP_OTHER, "not enough memory for matched values filtering" );
892                                 goto error_return;
893                         }
894                         e_flags = tmp;
895                         a_flags = (char *)(e_flags + i);
896                         memset( a_flags, 0, k );
897                         for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
898                                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
899                                 e_flags[i] = a_flags;
900                                 a_flags += j;
901                         }
902                         rc = filter_matched_values(op, aa, &e_flags) ; 
903                     
904                         if ( rc == -1 ) {
905 #ifdef NEW_LOGGING
906                                 LDAP_LOG( OPERATION, ERR, 
907                                         "send_search_entry: conn %lu "
908                                         "matched values filtering failed\n", 
909                                         op->o_connid : 0, 0, 0);
910 #else
911                                 Debug( LDAP_DEBUG_ANY,
912                                         "matched values filtering failed\n", 0, 0, 0 );
913 #endif
914 #ifdef LDAP_CONNECTIONLESS
915                         if (!op->o_conn || op->o_conn->c_is_udp == 0)
916 #endif
917                                 ber_free( ber, 1 );
918         
919                                 send_ldap_error( op, rs, LDAP_OTHER, "matched values filtering error" );
920                                 goto error_return;
921                         }
922                 }
923         }
924
925         for (a = aa, j=0; a != NULL; a = a->a_next, j++ ) {
926                 AttributeDescription *desc = a->a_desc;
927
928                 if ( rs->sr_attrs == NULL ) {
929                         /* all attrs request, skip operational attributes */
930                         if( is_at_operational( desc->ad_type ) ) {
931                                 continue;
932                         }
933
934                 } else {
935                         /* specific attrs requested */
936                         if( is_at_operational( desc->ad_type ) ) {
937                                 if( !opattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
938                                         continue;
939                                 }
940                         } else {
941                                 if (!userattrs && !ad_inlist( desc, rs->sr_attrs ) )
942                                 {
943                                         continue;
944                                 }
945                         }
946                 }
947
948                 if ( ! access_allowed( op, rs->sr_entry, desc, NULL,
949                         ACL_READ, &acl_state ) )
950                 {
951 #ifdef NEW_LOGGING
952                         LDAP_LOG( ACL, INFO, 
953                                 "send_search_entry: conn %lu "
954                                 "access to attribute %s not allowed\n",
955                                 op->o_connid, desc->ad_cname.bv_val, 0 );
956 #else
957                         Debug( LDAP_DEBUG_ACL, "send_search_entry: access to attribute %s "
958                                         "not allowed\n",
959                                         desc->ad_cname.bv_val, 0, 0 );
960 #endif
961
962                         continue;
963                 }
964
965                 rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname );
966                 if ( rc == -1 ) {
967 #ifdef NEW_LOGGING
968                         LDAP_LOG( OPERATION, ERR, 
969                                 "send_search_entry: conn %lu  "
970                                 "ber_printf failed\n", op->o_connid, 0, 0 );
971 #else
972                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
973 #endif
974
975 #ifdef LDAP_CONNECTIONLESS
976                         if (!op->o_conn || op->o_conn->c_is_udp == 0)
977 #endif
978                         ber_free_buf( ber );
979                         send_ldap_error( op, rs, LDAP_OTHER, "encoding description error" );
980
981                         attrs_free( aa );
982                         goto error_return;
983                 }
984
985                 if ( ! op->ors_attrsonly ) {
986                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
987                                 if ( ! access_allowed( op, rs->sr_entry,
988                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
989                                 {
990 #ifdef NEW_LOGGING
991                                         LDAP_LOG( ACL, INFO, 
992                                                 "send_search_entry: conn %lu "
993                                                 "access to %s, value %d not allowed\n",
994                                                 op->o_connid, desc->ad_cname.bv_val, i );
995 #else
996                                         Debug( LDAP_DEBUG_ACL,
997                                                 "send_search_entry: access to attribute %s, "
998                                                 "value %d not allowed\n",
999                                                 desc->ad_cname.bv_val, i, 0 );
1000 #endif
1001
1002                                         continue;
1003                                 }
1004
1005                                 if ( op->vrFilter && e_flags[j][i] == 0 ){
1006                                         continue;
1007                                 }
1008
1009                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
1010 #ifdef NEW_LOGGING
1011                                         LDAP_LOG( OPERATION, ERR, 
1012                                                 "send_search_entry: conn %lu  ber_printf failed\n", 
1013                                                 op->o_connid, 0, 0 );
1014 #else
1015                                         Debug( LDAP_DEBUG_ANY,
1016                                             "ber_printf failed\n", 0, 0, 0 );
1017 #endif
1018
1019 #ifdef LDAP_CONNECTIONLESS
1020                                         if (!op->o_conn || op->o_conn->c_is_udp == 0)
1021 #endif
1022                                         ber_free_buf( ber );
1023                                         send_ldap_error( op, rs, LDAP_OTHER, "encoding values error" );
1024                                         attrs_free( aa );
1025                                         goto error_return;
1026                                 }
1027                         }
1028                 }
1029
1030                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
1031 #ifdef NEW_LOGGING
1032                         LDAP_LOG( OPERATION, ERR, 
1033                                 "send_search_entry: conn %lu  ber_printf failed\n",
1034                                 op->o_connid, 0, 0 );
1035 #else
1036                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1037 #endif
1038
1039 #ifdef LDAP_CONNECTIONLESS
1040                         if (!op->o_conn || op->o_conn->c_is_udp == 0)
1041 #endif
1042                         ber_free_buf( ber );
1043                         send_ldap_error( op, rs, LDAP_OTHER, "encode end error" );
1044
1045                         attrs_free( aa );
1046                         goto error_return;
1047                 }
1048         }
1049
1050 #ifdef LDAP_SLAPI
1051         /*
1052          * First, setup the computed attribute context that is
1053          * passed to all plugins.
1054          */
1055         ctx.cac_pb = op->o_pb;
1056         ctx.cac_attrs = rs->sr_attrs;
1057         ctx.cac_attrsonly = op->ors_attrsonly;
1058         ctx.cac_userattrs = userattrs;
1059         ctx.cac_opattrs = opattrs;
1060         ctx.cac_acl_state = acl_state;
1061         ctx.cac_private = (void *)ber;
1062
1063         /*
1064          * For each client requested attribute, call the plugins.
1065          */
1066         if ( rs->sr_attrs != NULL ) {
1067                 for ( anp = rs->sr_attrs; anp->an_name.bv_val != NULL; anp++ ) {
1068                         rc = compute_evaluator( &ctx, anp->an_name.bv_val, rs->sr_entry, slapi_x_compute_output_ber );
1069                         if ( rc == 1 ) {
1070                                 break;
1071                         }
1072                 }
1073         } else {
1074                 /*
1075                  * Technically we shouldn't be returning operational attributes
1076                  * when the user requested only user attributes. We'll let the
1077                  * plugin decide whether to be naughty or not.
1078                  */
1079                 rc = compute_evaluator( &ctx, "*", rs->sr_entry, slapi_x_compute_output_ber );
1080         }
1081         if ( rc == 1 ) {
1082                 ber_free_buf( ber );
1083                 send_ldap_error( op, rs, LDAP_OTHER, "computed attribute error" );
1084                 goto error_return;
1085         }
1086 #endif /* LDAP_SLAPI */
1087
1088         /* free e_flags */
1089         if ( e_flags ) {
1090                 free( e_flags );
1091                 e_flags = NULL;
1092         }
1093
1094         attrs_free( aa );
1095         rc = ber_printf( ber, /*{{*/ "}N}" );
1096
1097         if( rc != -1 && rs->sr_ctrls != NULL ) {
1098                 rc = send_ldap_controls( ber, rs->sr_ctrls );
1099         }
1100
1101 #ifdef LDAP_CONNECTIONLESS
1102         if( op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2 ) {
1103                 ; /* empty, skip following if */
1104         } else
1105 #endif
1106         if( rc != -1 ) {
1107                 rc = ber_printf( ber, /*{*/ "N}" );
1108         }
1109
1110         if ( rc == -1 ) {
1111 #ifdef NEW_LOGGING
1112                 LDAP_LOG( OPERATION, ERR, 
1113                         "send_search_entry: conn %lu ber_printf failed\n", 
1114                         op->o_connid, 0, 0 );
1115 #else
1116                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1117 #endif
1118
1119 #ifdef LDAP_CONNECTIONLESS
1120                 if (!op->o_conn || op->o_conn->c_is_udp == 0)
1121 #endif
1122                 ber_free_buf( ber );
1123                 send_ldap_error( op, rs, LDAP_OTHER, "encode entry end error" );
1124                 return( 1 );
1125         }
1126
1127 #ifdef LDAP_CONNECTIONLESS
1128         if (!op->o_conn || op->o_conn->c_is_udp == 0) {
1129 #endif
1130         bytes = op->o_noop ? 0 : send_ldap_ber( op->o_conn, ber );
1131         ber_free_buf( ber );
1132
1133         if ( bytes < 0 ) {
1134 #ifdef NEW_LOGGING
1135                 LDAP_LOG( OPERATION, ERR, 
1136                            "send_search_entry: conn %lu  ber write failed.\n", 
1137                            op->o_connid, 0, 0 );
1138 #else
1139                 Debug( LDAP_DEBUG_ANY,
1140                         "send_search_entry: ber write failed\n",
1141                         0, 0, 0 );
1142 #endif
1143
1144                 return -1;
1145         }
1146
1147         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1148         num_bytes_sent += bytes;
1149         num_entries_sent++;
1150         num_pdu_sent++;
1151         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1152
1153 #ifdef LDAP_CONNECTIONLESS
1154         }
1155 #endif
1156
1157         Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu ENTRY dn=\"%s\"\n",
1158             op->o_connid, op->o_opid, rs->sr_entry->e_dn, 0, 0 );
1159
1160 #ifdef NEW_LOGGING
1161         LDAP_LOG( OPERATION, ENTRY, 
1162                 "send_search_entry: conn %lu exit.\n", op->o_connid, 0, 0 );
1163 #else
1164         Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
1165 #endif
1166
1167         rc = 0;
1168
1169 error_return:;
1170         if ( e_flags ) free( e_flags );
1171         return( rc );
1172 }
1173
1174 int
1175 slap_send_search_reference( Operation *op, SlapReply *rs )
1176 {
1177         char berbuf[LBER_ELEMENT_SIZEOF];
1178         BerElement      *ber = (BerElement *)berbuf;
1179         int rc;
1180         int bytes;
1181
1182         AttributeDescription *ad_ref = slap_schema.si_ad_ref;
1183         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
1184
1185         rs->sr_type = REP_SEARCHREF;
1186         if (op->o_callback && op->o_callback->sc_sendreference) {
1187                 return op->o_callback->sc_sendreference( op, rs );
1188         }
1189
1190 #ifdef NEW_LOGGING
1191         LDAP_LOG( OPERATION, ENTRY, 
1192                 "send_search_reference: conn %lu  dn=\"%s\"\n", 
1193                 op->o_connid, rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)", 0 );
1194 #else
1195         Debug( LDAP_DEBUG_TRACE,
1196                 "=> send_search_reference: dn=\"%s\"\n",
1197                 rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)", 0, 0 );
1198 #endif
1199
1200         if (  rs->sr_entry && ! access_allowed( op, rs->sr_entry,
1201                 ad_entry, NULL, ACL_READ, NULL ) )
1202         {
1203 #ifdef NEW_LOGGING
1204                 LDAP_LOG( ACL, INFO, 
1205                         "send_search_reference: conn %lu        "
1206                         "access to entry %s not allowed\n",
1207                         op->o_connid, rs->sr_entry->e_dn, 0 );
1208 #else
1209                 Debug( LDAP_DEBUG_ACL,
1210                         "send_search_reference: access to entry not allowed\n",
1211                     0, 0, 0 );
1212 #endif
1213
1214                 return( 1 );
1215         }
1216
1217         if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry,
1218                 ad_ref, NULL, ACL_READ, NULL ) )
1219         {
1220 #ifdef NEW_LOGGING
1221                 LDAP_LOG( ACL, INFO, 
1222                         "send_search_reference: conn %lu access "
1223                         "to reference not allowed.\n", op->o_connid, 0, 0 );
1224 #else
1225                 Debug( LDAP_DEBUG_ACL,
1226                         "send_search_reference: access "
1227                         "to reference not allowed\n",
1228                     0, 0, 0 );
1229 #endif
1230
1231                 return( 1 );
1232         }
1233
1234 #ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
1235         if( op->o_domain_scope ) {
1236 #ifdef NEW_LOGGING
1237                 LDAP_LOG( OPERATION, ERR, 
1238                         "send_search_reference: conn %lu domainScope control in (%s).\n",
1239                         op->o_connid, rs->sr_entry->e_dn, 0 );
1240 #else
1241                 Debug( LDAP_DEBUG_ANY,
1242                         "send_search_reference: domainScope control in (%s)\n", 
1243                         rs->sr_entry->e_dn, 0, 0 );
1244 #endif
1245
1246                 return( 0 );
1247         }
1248 #endif
1249
1250         if( rs->sr_ref == NULL ) {
1251 #ifdef NEW_LOGGING
1252                 LDAP_LOG( OPERATION, ERR, 
1253                         "send_search_reference: conn %lu null ref in (%s).\n",
1254                         op->o_connid, rs->sr_entry ? rs->sr_entry->e_dn : "(null)", 0 );
1255 #else
1256                 Debug( LDAP_DEBUG_ANY,
1257                         "send_search_reference: null ref in (%s)\n", 
1258                         rs->sr_entry ? rs->sr_entry->e_dn : "(null)", 0, 0 );
1259 #endif
1260
1261                 return( 1 );
1262         }
1263
1264         if( op->o_protocol < LDAP_VERSION3 ) {
1265                 /* save the references for the result */
1266                 if( rs->sr_ref[0].bv_val != NULL ) {
1267                         if( value_add( &rs->sr_v2ref, rs->sr_ref ) )
1268                                 return LDAP_OTHER;
1269                 }
1270                 return 0;
1271         }
1272
1273 #ifdef LDAP_CONNECTIONLESS
1274         if (op->o_conn && op->o_conn->c_is_udp)
1275                 ber = op->o_res_ber;
1276         else
1277 #endif
1278         ber_init_w_nullc( ber, LBER_USE_DER );
1279
1280         rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid,
1281                 LDAP_RES_SEARCH_REFERENCE, rs->sr_ref );
1282
1283         if( rc != -1 && rs->sr_ctrls != NULL ) {
1284                 rc = send_ldap_controls( ber, rs->sr_ctrls );
1285         }
1286
1287         if( rc != -1 ) {
1288                 rc = ber_printf( ber, /*"{"*/ "N}" );
1289         }
1290
1291         if ( rc == -1 ) {
1292 #ifdef NEW_LOGGING
1293                 LDAP_LOG( OPERATION, ERR, 
1294                         "send_search_reference: conn %lu        "
1295                         "ber_printf failed.\n", op->o_connid, 0, 0 );
1296 #else
1297                 Debug( LDAP_DEBUG_ANY,
1298                         "send_search_reference: ber_printf failed\n", 0, 0, 0 );
1299 #endif
1300
1301 #ifdef LDAP_CONNECTIONLESS
1302                 if (!op->o_conn || op->o_conn->c_is_udp == 0)
1303 #endif
1304                 ber_free_buf( ber );
1305                 send_ldap_error( op, rs, LDAP_OTHER, "encode DN error" );
1306                 return -1;
1307         }
1308
1309 #ifdef LDAP_CONNECTIONLESS
1310         if (!op->o_conn || op->o_conn->c_is_udp == 0) {
1311 #endif
1312         bytes = op->o_noop ? 0 : send_ldap_ber( op->o_conn, ber );
1313         ber_free_buf( ber );
1314
1315         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1316         num_bytes_sent += bytes;
1317         num_refs_sent++;
1318         num_pdu_sent++;
1319         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1320 #ifdef LDAP_CONNECTIONLESS
1321         }
1322 #endif
1323
1324         Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu REF dn=\"%s\"\n",
1325                 op->o_connid, op->o_opid, rs->sr_entry ? rs->sr_entry->e_dn : "(null)", 0, 0 );
1326
1327 #ifdef NEW_LOGGING
1328         LDAP_LOG( OPERATION, ENTRY, 
1329                 "send_search_reference: conn %lu exit.\n", op->o_connid, 0, 0 );
1330 #else
1331         Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 );
1332 #endif
1333
1334         return 0;
1335 }
1336
1337 int
1338 str2result(
1339     char        *s,
1340     int         *code,
1341     char        **matched,
1342     char        **info
1343 )
1344 {
1345         int     rc;
1346         char    *c;
1347
1348         *code = LDAP_SUCCESS;
1349         *matched = NULL;
1350         *info = NULL;
1351
1352         if ( strncasecmp( s, "RESULT", 6 ) != 0 ) {
1353 #ifdef NEW_LOGGING
1354                 LDAP_LOG( OPERATION, INFO, 
1355                         "str2result: (%s), expecting \"RESULT\"\n", s, 0, 0 );
1356 #else
1357                 Debug( LDAP_DEBUG_ANY, "str2result (%s) expecting \"RESULT\"\n",
1358                     s, 0, 0 );
1359 #endif
1360
1361                 return( -1 );
1362         }
1363
1364         rc = 0;
1365         while ( (s = strchr( s, '\n' )) != NULL ) {
1366                 *s++ = '\0';
1367                 if ( *s == '\0' ) {
1368                         break;
1369                 }
1370                 if ( (c = strchr( s, ':' )) != NULL ) {
1371                         c++;
1372                 }
1373
1374                 if ( strncasecmp( s, "code", 4 ) == 0 ) {
1375                         if ( c != NULL ) {
1376                                 *code = atoi( c );
1377                         }
1378                 } else if ( strncasecmp( s, "matched", 7 ) == 0 ) {
1379                         if ( c != NULL ) {
1380                                 *matched = c;
1381                         }
1382                 } else if ( strncasecmp( s, "info", 4 ) == 0 ) {
1383                         if ( c != NULL ) {
1384                                 *info = c;
1385                         }
1386                 } else {
1387 #ifdef NEW_LOGGING
1388                         LDAP_LOG( OPERATION, INFO, "str2result: (%s) unknown.\n", s, 0, 0 );
1389 #else
1390                         Debug( LDAP_DEBUG_ANY, "str2result (%s) unknown\n",
1391                             s, 0, 0 );
1392 #endif
1393
1394                         rc = -1;
1395                 }
1396         }
1397
1398         return( rc );
1399 }