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