]> git.sur5r.net Git - openldap/blob - servers/slapd/result.c
1d87d215067144083887ba7c21ac932005ef1c66
[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 #ifdef LDAP_CONNECTIONLESS
246         if (conn->c_is_udp)
247                 ber = op->o_res_ber;
248         else
249 #endif
250
251         ber_init_w_nullc( ber, LBER_USE_DER );
252
253 #ifdef NEW_LOGGING
254         LDAP_LOG( OPERATION, ENTRY, 
255                 "send_ldap_response:  msgid=%d tag=%lu err=%d\n",
256                 msgid, tag, err );
257 #else
258         Debug( LDAP_DEBUG_TRACE,
259                 "send_ldap_response: msgid=%d tag=%lu err=%d\n",
260                 msgid, tag, err );
261 #endif
262
263         if( ref ) {
264 #ifdef NEW_LOGGING
265                 LDAP_LOG( OPERATION, ARGS, 
266                         "send_ldap_response: conn %lu  ref=\"%s\"\n",
267                         conn ? conn->c_connid : 0, 
268                         ref[0].bv_val ? ref[0].bv_val : "NULL" , 0 );
269 #else
270                 Debug( LDAP_DEBUG_ARGS, "send_ldap_response: ref=\"%s\"\n",
271                         ref[0].bv_val ? ref[0].bv_val : "NULL",
272                         NULL, NULL );
273 #endif
274         }
275
276 #ifdef LDAP_CONNECTIONLESS
277         if (conn->c_is_udp && conn->c_protocol == LDAP_VERSION2) {
278                 rc = ber_printf( ber, "t{ess" /*"}}"*/,
279                         tag, err,
280                 matched == NULL ? "" : matched,
281                 text == NULL ? "" : text );
282         } else 
283 #endif
284         {
285             rc = ber_printf( ber, "{it{ess" /*"}}"*/,
286                 msgid, tag, err,
287                 matched == NULL ? "" : matched,
288                 text == NULL ? "" : text );
289         }
290
291         if( rc != -1 ) {
292                 if ( ref != NULL ) {
293                         assert( err == LDAP_REFERRAL );
294                         rc = ber_printf( ber, "t{W}",
295                                 LDAP_TAG_REFERRAL, ref );
296                 } else {
297                         assert( err != LDAP_REFERRAL );
298                 }
299         }
300
301         if( rc != -1 && sasldata != NULL ) {
302                 rc = ber_printf( ber, "tO",
303                         LDAP_TAG_SASL_RES_CREDS, sasldata );
304         }
305
306         if( rc != -1 && resoid != NULL ) {
307                 rc = ber_printf( ber, "ts",
308                         LDAP_TAG_EXOP_RES_OID, resoid );
309         }
310
311         if( rc != -1 && resdata != NULL ) {
312                 rc = ber_printf( ber, "tO",
313                         LDAP_TAG_EXOP_RES_VALUE, resdata );
314         }
315
316         if( rc != -1 ) {
317                 rc = ber_printf( ber, /*"{"*/ "N}" );
318         }
319
320         if( rc != -1 && ctrls != NULL ) {
321                 rc = send_ldap_controls( ber, ctrls );
322         }
323
324         if( rc != -1 ) {
325                 rc = ber_printf( ber, /*"{"*/ "N}" );
326         }
327
328         if ( rc == -1 ) {
329 #ifdef NEW_LOGGING
330                 LDAP_LOG( OPERATION, ERR, 
331                         "send_ldap_response: conn %lu  ber_printf failed\n",
332                         conn ? conn->c_connid : 0, 0, 0 );
333 #else
334                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
335 #endif
336
337 #ifdef LDAP_CONNECTIONLESS
338                 if (conn->c_is_udp == 0)
339 #endif
340                 ber_free_buf( ber );
341                 return;
342         }
343
344         /* send BER */
345         bytes = send_ldap_ber( conn, ber );
346 #ifdef LDAP_CONNECTIONLESS
347         if (conn->c_is_udp == 0)
348 #endif
349         ber_free_buf( ber );
350
351         if ( bytes < 0 ) {
352 #ifdef NEW_LOGGING
353                 LDAP_LOG( OPERATION, ERR, 
354                         "send_ldap_response: conn %lu ber write failed\n",
355                         conn ? conn->c_connid : 0, 0, 0 );
356 #else
357                 Debug( LDAP_DEBUG_ANY,
358                         "send_ldap_response: ber write failed\n",
359                         0, 0, 0 );
360 #endif
361
362                 return;
363         }
364
365 #ifdef LDAP_SLAPI
366         slapi_pblock_set( op->o_pb, SLAPI_RESULT_CODE, (void *)err );
367         slapi_pblock_set( op->o_pb, SLAPI_RESULT_MATCHED, ( matched != NULL ) ? (void *)ch_strdup( matched ) : NULL );
368         slapi_pblock_set( op->o_pb, SLAPI_RESULT_TEXT, ( text != NULL ) ? (void *)ch_strdup( text ) : NULL );
369 #endif /* LDAP_SLAPI */
370
371         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
372         num_bytes_sent += bytes;
373         num_pdu_sent++;
374         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
375         return;
376 }
377
378
379 void
380 send_ldap_disconnect(
381     Connection  *conn,
382     Operation   *op,
383     ber_int_t   err,
384     const char  *text
385 )
386 {
387         ber_tag_t tag;
388         ber_int_t msgid;
389         char *reqoid;
390
391 #define LDAP_UNSOLICITED_ERROR(e) \
392         (  (e) == LDAP_PROTOCOL_ERROR \
393         || (e) == LDAP_STRONG_AUTH_REQUIRED \
394         || (e) == LDAP_UNAVAILABLE )
395
396         assert( LDAP_UNSOLICITED_ERROR( err ) );
397
398 #ifdef NEW_LOGGING
399         LDAP_LOG( OPERATION, ENTRY, 
400                 "send_ldap_disconnect: conn %lu  %d:%s\n",
401                 conn ? conn->c_connid : 0, err, text ? text : "" );
402 #else
403         Debug( LDAP_DEBUG_TRACE,
404                 "send_ldap_disconnect %d:%s\n",
405                 err, text ? text : "", NULL );
406 #endif
407
408
409         if ( op->o_protocol < LDAP_VERSION3 ) {
410                 reqoid = NULL;
411                 tag = req2res( op->o_tag );
412                 msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
413
414         } else {
415                 reqoid = LDAP_NOTICE_DISCONNECT;
416                 tag = LDAP_RES_EXTENDED;
417                 msgid = 0;
418         }
419
420         send_ldap_response( conn, op, tag, msgid,
421                 err, NULL, text, NULL,
422                 reqoid, NULL, NULL, NULL );
423
424         Statslog( LDAP_DEBUG_STATS,
425             "conn=%lu op=%lu DISCONNECT tag=%lu err=%d text=%s\n",
426                 op->o_connid, op->o_opid, tag, err, text ? text : "" );
427 }
428
429 void
430 slap_send_ldap_result(
431     Connection  *conn,
432     Operation   *op,
433     ber_int_t   err,
434     const char  *matched,
435     const char  *text,
436         BerVarray ref,
437         LDAPControl **ctrls
438 )
439 {
440         ber_tag_t tag;
441         ber_int_t msgid;
442         char *tmp = NULL;
443
444         assert( !LDAP_API_ERROR( err ) );
445
446 #ifdef NEW_LOGGING
447         LDAP_LOG( OPERATION, ENTRY, 
448                 "send_ldap_result: conn %lu op=%lu p=%d\n",
449                 op->o_connid, op->o_opid, op->o_protocol );
450 #else
451         Debug( LDAP_DEBUG_TRACE,
452                 "send_ldap_result: conn=%lu op=%lu p=%d\n",
453                 op->o_connid, op->o_opid, op->o_protocol );
454 #endif
455
456 #ifdef NEW_LOGGING
457         LDAP_LOG( OPERATION, ARGS, 
458                 "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n",
459                 err, matched ? matched : "", text ? text : "" );
460 #else
461         Debug( LDAP_DEBUG_ARGS,
462                 "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n",
463                 err, matched ?  matched : "", text ? text : "" );
464 #endif
465
466
467         if( ref ) {
468 #ifdef NEW_LOGGING
469                 LDAP_LOG( OPERATION, ARGS, 
470                         "send_ldap_result: referral=\"%s\"\n",
471                         ref[0].bv_val ? ref[0].bv_val : "NULL", 0, 0 );
472 #else
473                 Debug( LDAP_DEBUG_ARGS,
474                         "send_ldap_result: referral=\"%s\"\n",
475                         ref[0].bv_val ? ref[0].bv_val : "NULL",
476                         NULL, NULL );
477 #endif
478         }
479
480         assert( err != LDAP_PARTIAL_RESULTS );
481
482         if ( err == LDAP_REFERRAL ) {
483                 if( op->o_noreferrals ) {
484                         ref = NULL;
485                 }
486                 if( ref == NULL ) {
487                         err = LDAP_NO_SUCH_OBJECT;
488                 } else if ( op->o_protocol < LDAP_VERSION3 ) {
489                         err = LDAP_PARTIAL_RESULTS;
490                 }
491         }
492
493         if ( op->o_protocol < LDAP_VERSION3 ) {
494                 tmp = v2ref( ref, text );
495                 text = tmp;
496                 ref = NULL;
497         }
498
499         tag = req2res( op->o_tag );
500         msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
501
502         send_ldap_response( conn, op, tag, msgid,
503                 err, matched, text, ref,
504                 NULL, NULL, NULL, ctrls );
505
506         Statslog( LDAP_DEBUG_STATS,
507             "conn=%lu op=%lu RESULT tag=%lu err=%d text=%s\n",
508                 op->o_connid, op->o_opid, tag, err, text ? text : "" );
509
510         if( tmp != NULL ) {
511                 ch_free(tmp);
512         }
513 }
514
515 void
516 send_ldap_sasl(
517     Connection  *conn,
518     Operation   *op,
519     ber_int_t   err,
520     const char  *matched,
521     const char  *text,
522         BerVarray ref,
523         LDAPControl **ctrls,
524         struct berval *cred
525 )
526 {
527         ber_tag_t tag;
528         ber_int_t msgid;
529
530 #ifdef NEW_LOGGING
531         LDAP_LOG( OPERATION, ENTRY, 
532                 "send_ldap_sasl: conn %lu err=%d len=%lu\n",
533                 op->o_connid, err, cred ? cred->bv_len : -1 );
534 #else
535         Debug( LDAP_DEBUG_TRACE, "send_ldap_sasl: err=%d len=%ld\n",
536                 err, cred ? (long) cred->bv_len : -1, NULL );
537 #endif
538
539
540         tag = req2res( op->o_tag );
541         msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
542
543         send_ldap_response( conn, op, tag, msgid,
544                 err, matched, text, ref,
545                 NULL, NULL, cred, ctrls  );
546 }
547
548 void
549 slap_send_ldap_extended(
550     Connection  *conn,
551     Operation   *op,
552     ber_int_t   err,
553     const char  *matched,
554     const char  *text,
555     BerVarray   refs,
556     const char          *rspoid,
557         struct berval *rspdata,
558         LDAPControl **ctrls
559 )
560 {
561         ber_tag_t tag;
562         ber_int_t msgid;
563
564 #ifdef NEW_LOGGING
565         LDAP_LOG( OPERATION, ENTRY, 
566                 "send_ldap_extended: err=%d oid=%s len=%ld\n",
567                 err, rspoid ? rspoid : "",
568                 rspdata != NULL ? rspdata->bv_len : 0 );
569 #else
570         Debug( LDAP_DEBUG_TRACE,
571                 "send_ldap_extended: err=%d oid=%s len=%ld\n",
572                 err,
573                 rspoid ? rspoid : "",
574                 rspdata != NULL ? rspdata->bv_len : 0 );
575 #endif
576
577         tag = req2res( op->o_tag );
578         msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
579
580         send_ldap_response( conn, op, tag, msgid,
581                 err, matched, text, refs,
582                 rspoid, rspdata, NULL, ctrls );
583 }
584
585
586 void
587 slap_send_search_result(
588     Connection  *conn,
589     Operation   *op,
590     ber_int_t   err,
591     const char  *matched,
592         const char      *text,
593     BerVarray   refs,
594         LDAPControl **ctrls,
595     int         nentries
596 )
597 {
598         ber_tag_t tag;
599         ber_int_t msgid;
600         char *tmp = NULL;
601
602         assert( !LDAP_API_ERROR( err ) );
603
604         if (op->o_callback && op->o_callback->sc_sresult) {
605                 op->o_callback->sc_sresult(conn, op, err, matched, text, refs,
606                         ctrls, nentries);
607                 return;
608         }
609
610 #ifdef NEW_LOGGING
611         LDAP_LOG( OPERATION, ENTRY, 
612                 "send_search_result: err=%d matched=\"%s\" text=\"%s\"\n",
613                 err, matched ? matched : "", text ? text : "" );
614 #else
615         Debug( LDAP_DEBUG_TRACE,
616                 "send_search_result: err=%d matched=\"%s\" text=\"%s\"\n",
617                 err, matched ?  matched : "", text ? text : "" );
618 #endif
619
620
621         assert( err != LDAP_PARTIAL_RESULTS );
622
623         if( op->o_protocol < LDAP_VERSION3 ) {
624                 /* send references in search results */
625                 if( err == LDAP_REFERRAL ) {
626                         err = LDAP_PARTIAL_RESULTS;
627                 }
628
629                 tmp = v2ref( refs, text );
630                 text = tmp;
631                 refs = NULL;
632
633         } else {
634                 /* don't send references in search results */
635                 assert( refs == NULL );
636                 refs = NULL;
637
638                 if( err == LDAP_REFERRAL ) {
639                         err = LDAP_SUCCESS;
640                 }
641         }
642
643         tag = req2res( op->o_tag );
644         msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
645
646         send_ldap_response( conn, op, tag, msgid,
647                 err, matched, text, refs,
648                 NULL, NULL, NULL, ctrls );
649
650         {
651         char nbuf[64];
652         snprintf( nbuf, sizeof nbuf, "%d nentries=%d", err, nentries );
653
654         Statslog( LDAP_DEBUG_STATS,
655             "conn=%lu op=%lu SEARCH RESULT tag=%lu err=%s text=%s\n",
656                 op->o_connid, op->o_opid, tag, nbuf, text ? text : "" );
657         }
658
659         if (tmp != NULL) {
660             ch_free(tmp);
661         }
662 }
663
664 int
665 slap_send_search_entry(
666     Backend     *be,
667     Connection  *conn,
668     Operation   *op,
669     Entry       *e,
670     AttributeName       *attrs,
671     int         attrsonly,
672         LDAPControl **ctrls
673 )
674 {
675         char berbuf[LBER_ELEMENT_SIZEOF];
676         BerElement      *ber = (BerElement *)berbuf;
677         Attribute       *a, *aa;
678         int             i, j, rc=-1, bytes;
679         char            *edn;
680         int             userattrs;
681         int             opattrs;
682         AccessControlState acl_state = ACL_STATE_INIT;
683 #ifdef LDAP_SLAPI
684         /* Support for computed attribute plugins */
685         computed_attr_context    ctx;
686         AttributeName   *anp;
687 #endif
688
689         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
690
691         /* a_flags: array of flags telling if the i-th element will be
692          *          returned or filtered out
693          * e_flags: array of a_flags
694          */
695         char **e_flags = NULL;
696
697         if (op->o_callback && op->o_callback->sc_sendentry) {
698                 return op->o_callback->sc_sendentry( be, conn, op, e, attrs,
699                         attrsonly, ctrls );
700         }
701
702 #ifdef NEW_LOGGING
703         LDAP_LOG( OPERATION, ENTRY, 
704                 "send_search_entry: conn %lu    dn=\"%s\"%s\n",
705                 op->o_connid, e->e_dn, attrsonly ? " (attrsOnly)" : "" );
706 #else
707         Debug( LDAP_DEBUG_TRACE,
708                 "=> send_search_entry: dn=\"%s\"%s\n",
709                 e->e_dn, attrsonly ? " (attrsOnly)" : "", 0 );
710 #endif
711
712         if ( ! access_allowed( be, conn, op, e,
713                 ad_entry, NULL, ACL_READ, NULL ) )
714         {
715 #ifdef NEW_LOGGING
716                 LDAP_LOG( ACL, INFO, 
717                         "send_search_entry: conn %lu access to entry (%s) not allowed\n", 
718                         op->o_connid, e->e_dn, 0 );
719 #else
720                 Debug( LDAP_DEBUG_ACL,
721                         "send_search_entry: access to entry not allowed\n",
722                     0, 0, 0 );
723 #endif
724
725                 return( 1 );
726         }
727
728         edn = e->e_ndn;
729
730 #ifdef LDAP_CONNECTIONLESS
731         if (conn->c_is_udp)
732             ber = op->o_res_ber;
733         else
734 #endif
735         ber_init_w_nullc( ber, LBER_USE_DER );
736
737 #ifdef LDAP_CONNECTIONLESS
738         if (conn->c_is_udp && conn->c_protocol == LDAP_VERSION2) {
739             rc = ber_printf(ber, "t{0{" /*}}*/,
740                 LDAP_RES_SEARCH_ENTRY, &e->e_name);
741         } else
742 #endif
743         {
744             rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
745                 LDAP_RES_SEARCH_ENTRY, &e->e_name );
746         }
747
748         if ( rc == -1 ) {
749 #ifdef NEW_LOGGING
750                 LDAP_LOG( OPERATION, ERR, 
751                         "send_search_entry: conn %lu  ber_printf failed\n", 
752                         op->o_connid, 0, 0 );
753 #else
754                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
755 #endif
756
757 #ifdef LDAP_CONNECTIONLESS
758                 if (conn->c_is_udp == 0)
759 #endif
760                 ber_free_buf( ber );
761                 send_ldap_result( conn, op, LDAP_OTHER,
762                     NULL, "encoding DN error", NULL, NULL );
763                 goto error_return;
764         }
765
766         /* check for special all user attributes ("*") type */
767         userattrs = ( attrs == NULL ) ? 1
768                 : an_find( attrs, &AllUser );
769
770         /* check for special all operational attributes ("+") type */
771         opattrs = ( attrs == NULL ) ? 0
772                 : an_find( attrs, &AllOper );
773
774         /* create an array of arrays of flags. Each flag corresponds
775          * to particular value of attribute and equals 1 if value matches
776          * to ValuesReturnFilter or 0 if not
777          */     
778         if ( op->vrFilter != NULL ) {
779                 int     k = 0;
780                 size_t  size;
781
782                 for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
783                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
784                 }
785
786                 size = i * sizeof(char *) + k;
787                 if ( size > 0 ) {
788                         char    *a_flags;
789                         e_flags = SLAP_CALLOC ( 1, i * sizeof(char *) + k );
790                         if( e_flags == NULL ) {
791 #ifdef NEW_LOGGING
792                                 LDAP_LOG( OPERATION, ERR, 
793                                         "send_search_entry: conn %lu SLAP_CALLOC failed\n",
794                                         conn ? conn->c_connid : 0, 0, 0 );
795 #else
796                         Debug( LDAP_DEBUG_ANY, 
797                                         "send_search_entry: SLAP_CALLOC failed\n", 0, 0, 0 );
798 #endif
799                                 ber_free( ber, 1 );
800         
801                                 send_ldap_result( conn, op, LDAP_OTHER,
802                                         NULL, "memory error", 
803                                         NULL, NULL );
804                                 goto error_return;
805                         }
806                         a_flags = (char *)(e_flags + i);
807                         memset( a_flags, 0, k );
808                         for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
809                                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
810                                 e_flags[i] = a_flags;
811                                 a_flags += j;
812                         }
813         
814                         rc = filter_matched_values(be, conn, op, e->e_attrs, &e_flags) ; 
815                         if ( rc == -1 ) {
816 #ifdef NEW_LOGGING
817                                 LDAP_LOG( OPERATION, ERR, 
818                                         "send_search_entry: conn %lu matched values filtering failed\n",
819                                         conn ? conn->c_connid : 0, 0, 0 );
820 #else
821                         Debug( LDAP_DEBUG_ANY,
822                                         "matched values filtering failed\n", 0, 0, 0 );
823 #endif
824 #ifdef LDAP_CONNECTIONLESS
825                         if (conn->c_is_udp == 0)
826 #endif
827                                 ber_free( ber, 1 );
828         
829                                 send_ldap_result( conn, op, LDAP_OTHER,
830                                         NULL, "matched values filtering error", 
831                                         NULL, NULL );
832                                 goto error_return;
833                         }
834                 }
835         }
836
837         for ( a = e->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) {
838                 AttributeDescription *desc = a->a_desc;
839
840                 if ( attrs == NULL ) {
841                         /* all attrs request, skip operational attributes */
842                         if( is_at_operational( desc->ad_type ) ) {
843                                 continue;
844                         }
845
846                 } else {
847                         /* specific attrs requested */
848                         if ( is_at_operational( desc->ad_type ) ) {
849                                 if( !opattrs && !ad_inlist( desc, attrs ) ) {
850                                         continue;
851                                 }
852
853                         } else {
854                                 if (!userattrs && !ad_inlist( desc, attrs ) ) {
855                                         continue;
856                                 }
857                         }
858                 }
859
860                 if ( ! access_allowed( be, conn, op, e, desc, NULL,
861                         ACL_READ, &acl_state ) )
862                 {
863 #ifdef NEW_LOGGING
864                         LDAP_LOG( ACL, INFO, 
865                                 "send_search_entry: conn %lu  access to attribute %s not "
866                                 "allowed\n", op->o_connid, desc->ad_cname.bv_val, 0 );
867 #else
868                         Debug( LDAP_DEBUG_ACL, "acl: "
869                                 "access to attribute %s not allowed\n",
870                             desc->ad_cname.bv_val, 0, 0 );
871 #endif
872                         continue;
873                 }
874
875                 if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
876 #ifdef NEW_LOGGING
877                         LDAP_LOG( OPERATION, ERR, 
878                                 "send_search_entry: conn %lu  ber_printf failed\n", 
879                                 op->o_connid, 0, 0 );
880 #else
881                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
882 #endif
883
884 #ifdef LDAP_CONNECTIONLESS
885                         if (conn->c_is_udp == 0)
886 #endif
887                         ber_free_buf( ber );
888                         send_ldap_result( conn, op, LDAP_OTHER,
889                             NULL, "encoding description error", NULL, NULL );
890                         goto error_return;
891                 }
892
893                 if ( ! attrsonly ) {
894                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
895                                 if ( ! access_allowed( be, conn, op, e,
896                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
897                                 {
898 #ifdef NEW_LOGGING
899                                         LDAP_LOG( ACL, INFO, 
900                                                 "send_search_entry: conn %lu "
901                                                 "access to attribute %s, value %d not allowed\n",
902                                                 op->o_connid, desc->ad_cname.bv_val, i );
903 #else
904                                         Debug( LDAP_DEBUG_ACL,
905                                                 "acl: access to attribute %s, "
906                                                 "value %d not allowed\n",
907                                                 desc->ad_cname.bv_val, i, 0 );
908 #endif
909
910                                         continue;
911                                 }
912
913                                 if ( op->vrFilter && e_flags[j][i] == 0 ){
914                                         continue;
915                                 }
916
917                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
918 #ifdef NEW_LOGGING
919                                         LDAP_LOG( OPERATION, ERR, 
920                                                 "send_search_entry: conn %lu  "
921                                                 "ber_printf failed.\n", op->o_connid, 0, 0 );
922 #else
923                                         Debug( LDAP_DEBUG_ANY,
924                                             "ber_printf failed\n", 0, 0, 0 );
925 #endif
926
927 #ifdef LDAP_CONNECTIONLESS
928                                         if (conn->c_is_udp == 0)
929 #endif
930                                         ber_free_buf( ber );
931                                         send_ldap_result( conn, op, LDAP_OTHER,
932                                                 NULL, "encoding values error",
933                                                 NULL, NULL );
934                                         goto error_return;
935                                 }
936                         }
937                 }
938
939                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
940 #ifdef NEW_LOGGING
941                         LDAP_LOG( OPERATION, ERR, 
942                                 "send_search_entry: conn %lu ber_printf failed\n", 
943                                 op->o_connid, 0, 0 );
944 #else
945                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
946 #endif
947
948 #ifdef LDAP_CONNECTIONLESS
949                         if (conn->c_is_udp == 0)
950 #endif
951                         ber_free_buf( ber );
952                         send_ldap_result( conn, op, LDAP_OTHER,
953                             NULL, "encode end error", NULL, NULL );
954                         goto error_return;
955                 }
956         }
957
958         /* eventually will loop through generated operational attributes */
959         /* only have subschemaSubentry implemented */
960         aa = backend_operational( be, conn, op, e, attrs, opattrs );
961
962         if ( aa != NULL && op->vrFilter != NULL ) {
963                 int     k = 0;
964                 size_t  size;
965
966                 for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
967                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
968                 }
969
970                 size = i * sizeof(char *) + k;
971                 if ( size > 0 ) {
972                         char    *a_flags, **tmp;
973                 
974                         /*
975                          * Reuse previous memory - we likely need less space
976                          * for operational attributes
977                          */
978                         tmp = SLAP_REALLOC ( e_flags, i * sizeof(char *) + k );
979                         if ( tmp == NULL ) {
980 #ifdef NEW_LOGGING
981                                 LDAP_LOG( OPERATION, ERR, 
982                                         "send_search_entry: conn %lu "
983                                         "not enough memory "
984                                         "for matched values filtering\n", 
985                                         conn ? conn->c_connid : 0, 0, 0);
986 #else
987                                 Debug( LDAP_DEBUG_ANY,
988                                         "send_search_entry: conn %lu "
989                                         "not enough memory "
990                                         "for matched values filtering\n",
991                                         conn ? conn->c_connid : 0, 0, 0 );
992 #endif
993                                 ber_free( ber, 1 );
994         
995                                 send_ldap_result( conn, op, LDAP_NO_MEMORY,
996                                         NULL, NULL, NULL, NULL );
997                                 goto error_return;
998                         }
999                         e_flags = tmp;
1000                         a_flags = (char *)(e_flags + i);
1001                         memset( a_flags, 0, k );
1002                         for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
1003                                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
1004                                 e_flags[i] = a_flags;
1005                                 a_flags += j;
1006                         }
1007                         rc = filter_matched_values(be, conn, op, aa, &e_flags) ; 
1008                     
1009                         if ( rc == -1 ) {
1010 #ifdef NEW_LOGGING
1011                                 LDAP_LOG( OPERATION, ERR, 
1012                                         "send_search_entry: conn %lu "
1013                                         "matched values filtering failed\n", 
1014                                         conn ? conn->c_connid : 0, 0, 0);
1015 #else
1016                                 Debug( LDAP_DEBUG_ANY,
1017                                         "matched values filtering failed\n", 0, 0, 0 );
1018 #endif
1019 #ifdef LDAP_CONNECTIONLESS
1020                         if (conn->c_is_udp == 0)
1021 #endif
1022                                 ber_free( ber, 1 );
1023         
1024                                 send_ldap_result( conn, op, LDAP_OTHER,
1025                                         NULL, "matched values filtering error", 
1026                                         NULL, NULL );
1027                                 goto error_return;
1028                         }
1029                 }
1030         }
1031
1032         for (a = aa, j=0; a != NULL; a = a->a_next, j++ ) {
1033                 AttributeDescription *desc = a->a_desc;
1034
1035                 if ( attrs == NULL ) {
1036                         /* all attrs request, skip operational attributes */
1037                         if( is_at_operational( desc->ad_type ) ) {
1038                                 continue;
1039                         }
1040
1041                 } else {
1042                         /* specific attrs requested */
1043                         if( is_at_operational( desc->ad_type ) ) {
1044                                 if( !opattrs && !ad_inlist( desc, attrs ) ) {
1045                                         continue;
1046                                 }
1047                         } else {
1048                                 if (!userattrs && !ad_inlist( desc, attrs ) )
1049                                 {
1050                                         continue;
1051                                 }
1052                         }
1053                 }
1054
1055                 if ( ! access_allowed( be, conn, op, e, desc, NULL,
1056                         ACL_READ, &acl_state ) )
1057                 {
1058 #ifdef NEW_LOGGING
1059                         LDAP_LOG( ACL, INFO, 
1060                                 "send_search_entry: conn %lu "
1061                                 "access to attribute %s not allowed\n",
1062                                 op->o_connid, desc->ad_cname.bv_val, 0 );
1063 #else
1064                         Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s "
1065                                         "not allowed\n",
1066                                         desc->ad_cname.bv_val, 0, 0 );
1067 #endif
1068
1069                         continue;
1070                 }
1071
1072                 rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname );
1073                 if ( rc == -1 ) {
1074 #ifdef NEW_LOGGING
1075                         LDAP_LOG( OPERATION, ERR, 
1076                                 "send_search_entry: conn %lu  "
1077                                 "ber_printf failed\n", op->o_connid, 0, 0 );
1078 #else
1079                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1080 #endif
1081
1082 #ifdef LDAP_CONNECTIONLESS
1083                         if (conn->c_is_udp == 0)
1084 #endif
1085                         ber_free_buf( ber );
1086                         send_ldap_result( conn, op, LDAP_OTHER,
1087                             NULL, "encoding description error", NULL, NULL );
1088
1089                         attrs_free( aa );
1090                         goto error_return;
1091                 }
1092
1093                 if ( ! attrsonly ) {
1094                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
1095                                 if ( ! access_allowed( be, conn, op, e,
1096                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
1097                                 {
1098 #ifdef NEW_LOGGING
1099                                         LDAP_LOG( ACL, INFO, 
1100                                                 "send_search_entry: conn %lu "
1101                                                 "access to %s, value %d not allowed\n",
1102                                                 op->o_connid, desc->ad_cname.bv_val, i );
1103 #else
1104                                         Debug( LDAP_DEBUG_ACL,
1105                                                 "acl: access to attribute %s, "
1106                                                 "value %d not allowed\n",
1107                                                 desc->ad_cname.bv_val, i, 0 );
1108 #endif
1109
1110                                         continue;
1111                                 }
1112
1113                                 if ( op->vrFilter && e_flags[j][i] == 0 ){
1114                                         continue;
1115                                 }
1116
1117                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
1118 #ifdef NEW_LOGGING
1119                                         LDAP_LOG( OPERATION, ERR, 
1120                                                 "send_search_entry: conn %lu  ber_printf failed\n", 
1121                                                 op->o_connid, 0, 0 );
1122 #else
1123                                         Debug( LDAP_DEBUG_ANY,
1124                                             "ber_printf failed\n", 0, 0, 0 );
1125 #endif
1126
1127 #ifdef LDAP_CONNECTIONLESS
1128                                         if (conn->c_is_udp == 0)
1129 #endif
1130                                         ber_free_buf( ber );
1131                                         send_ldap_result( conn, op, LDAP_OTHER,
1132                                                 NULL, "encoding values error", 
1133                                                 NULL, NULL );
1134
1135                                         attrs_free( aa );
1136                                         goto error_return;
1137                                 }
1138                         }
1139                 }
1140
1141                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
1142 #ifdef NEW_LOGGING
1143                         LDAP_LOG( OPERATION, ERR, 
1144                                 "send_search_entry: conn %lu  ber_printf failed\n",
1145                                 op->o_connid, 0, 0 );
1146 #else
1147                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1148 #endif
1149
1150 #ifdef LDAP_CONNECTIONLESS
1151                         if (conn->c_is_udp == 0)
1152 #endif
1153                         ber_free_buf( ber );
1154                         send_ldap_result( conn, op, LDAP_OTHER,
1155                             NULL, "encode end error", NULL, NULL );
1156
1157                         attrs_free( aa );
1158                         goto error_return;
1159                 }
1160         }
1161
1162 #ifdef LDAP_SLAPI
1163         /*
1164          * First, setup the computed attribute context that is
1165          * passed to all plugins.
1166          */
1167         ctx.cac_pb = op->o_pb;
1168         ctx.cac_attrs = attrs;
1169         ctx.cac_attrsonly = attrsonly;
1170         ctx.cac_userattrs = userattrs;
1171         ctx.cac_opattrs = opattrs;
1172         ctx.cac_acl_state = acl_state;
1173         ctx.cac_private = (void *)ber;
1174
1175         /*
1176          * For each client requested attribute, call the plugins.
1177          */
1178         if ( attrs != NULL ) {
1179                 for ( anp = attrs; anp->an_name.bv_val != NULL; anp++ ) {
1180                         rc = compute_evaluator( &ctx, anp->an_name.bv_val, e, slapi_x_compute_output_ber );
1181                         if ( rc == 1 ) {
1182                                 break;
1183                         }
1184                 }
1185         } else {
1186                 /*
1187                  * Technically we shouldn't be returning operational attributes
1188                  * when the user requested only user attributes. We'll let the
1189                  * plugin decide whether to be naughty or not.
1190                  */
1191                 rc = compute_evaluator( &ctx, "*", e, slapi_x_compute_output_ber );
1192         }
1193         if ( rc == 1 ) {
1194                 ber_free_buf( ber );
1195                 send_ldap_result( conn, op, LDAP_OTHER,
1196                         NULL, "computed attribute error", NULL, NULL );
1197                 goto error_return;
1198         }
1199 #endif /* LDAP_SLAPI */
1200
1201         /* free e_flags */
1202         if ( e_flags ) {
1203                 free( e_flags );
1204                 e_flags = NULL;
1205         }
1206
1207         attrs_free( aa );
1208         rc = ber_printf( ber, /*{{*/ "}N}" );
1209
1210         if( rc != -1 && ctrls != NULL ) {
1211                 rc = send_ldap_controls( ber, ctrls );
1212         }
1213
1214         if( rc != -1 ) {
1215                 rc = ber_printf( ber, /*{*/ "N}" );
1216         }
1217
1218         if ( rc == -1 ) {
1219 #ifdef NEW_LOGGING
1220                 LDAP_LOG( OPERATION, ERR, 
1221                         "send_search_entry: conn %lu ber_printf failed\n", 
1222                         op->o_connid, 0, 0 );
1223 #else
1224                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1225 #endif
1226
1227 #ifdef LDAP_CONNECTIONLESS
1228                 if (conn->c_is_udp == 0)
1229 #endif
1230                 ber_free_buf( ber );
1231                 send_ldap_result( conn, op, LDAP_OTHER,
1232                         NULL, "encode entry end error", NULL, NULL );
1233                 return( 1 );
1234         }
1235
1236 #ifdef LDAP_CONNECTIONLESS
1237         if (conn->c_is_udp == 0) {
1238 #endif
1239         bytes = op->o_noop ? 0 : send_ldap_ber( conn, ber );
1240         ber_free_buf( ber );
1241
1242         if ( bytes < 0 ) {
1243 #ifdef NEW_LOGGING
1244                 LDAP_LOG( OPERATION, ERR, 
1245                            "send_search_entry: conn %lu  ber write failed.\n", 
1246                            op->o_connid, 0, 0 );
1247 #else
1248                 Debug( LDAP_DEBUG_ANY,
1249                         "send_search_entry: ber write failed\n",
1250                         0, 0, 0 );
1251 #endif
1252
1253                 return -1;
1254         }
1255
1256         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1257         num_bytes_sent += bytes;
1258         num_entries_sent++;
1259         num_pdu_sent++;
1260         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1261
1262 #ifdef LDAP_CONNECTIONLESS
1263         }
1264 #endif
1265
1266         Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu ENTRY dn=\"%s\"\n",
1267             conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
1268
1269 #ifdef NEW_LOGGING
1270         LDAP_LOG( OPERATION, ENTRY, 
1271                 "send_search_entry: conn %lu exit.\n", op->o_connid, 0, 0 );
1272 #else
1273         Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
1274 #endif
1275
1276         rc = 0;
1277
1278 error_return:;
1279         if ( e_flags ) free( e_flags );
1280         return( rc );
1281 }
1282
1283 int
1284 slap_send_search_reference(
1285     Backend     *be,
1286     Connection  *conn,
1287     Operation   *op,
1288     Entry       *e,
1289         BerVarray refs,
1290         LDAPControl **ctrls,
1291     BerVarray *v2refs
1292 )
1293 {
1294         char berbuf[LBER_ELEMENT_SIZEOF];
1295         BerElement      *ber = (BerElement *)berbuf;
1296         int rc;
1297         int bytes;
1298
1299         AttributeDescription *ad_ref = slap_schema.si_ad_ref;
1300         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
1301
1302 #ifdef NEW_LOGGING
1303         LDAP_LOG( OPERATION, ENTRY, 
1304                 "send_search_reference: conn %lu  dn=\"%s\"\n", 
1305                 op->o_connid, e ? e->e_dn : "(null)", 0 );
1306 #else
1307         Debug( LDAP_DEBUG_TRACE,
1308                 "=> send_search_reference: dn=\"%s\"\n",
1309                 e ? e->e_dn : "(null)", 0, 0 );
1310 #endif
1311
1312         if (  e && ! access_allowed( be, conn, op, e,
1313                 ad_entry, NULL, ACL_READ, NULL ) )
1314         {
1315 #ifdef NEW_LOGGING
1316                 LDAP_LOG( ACL, INFO, 
1317                         "send_search_reference: conn %lu        "
1318                         "access to entry %s not allowed\n",
1319                         op->o_connid, e->e_dn, 0 );
1320 #else
1321                 Debug( LDAP_DEBUG_ACL,
1322                         "send_search_reference: access to entry not allowed\n",
1323                     0, 0, 0 );
1324 #endif
1325
1326                 return( 1 );
1327         }
1328
1329         if ( e && ! access_allowed( be, conn, op, e,
1330                 ad_ref, NULL, ACL_READ, NULL ) )
1331         {
1332 #ifdef NEW_LOGGING
1333                 LDAP_LOG( ACL, INFO, 
1334                         "send_search_reference: conn %lu access "
1335                         "to reference not allowed.\n", op->o_connid, 0, 0 );
1336 #else
1337                 Debug( LDAP_DEBUG_ACL,
1338                         "send_search_reference: access "
1339                         "to reference not allowed\n",
1340                     0, 0, 0 );
1341 #endif
1342
1343                 return( 1 );
1344         }
1345
1346         if( op->o_noreferrals ) {
1347 #ifdef NEW_LOGGING
1348                 LDAP_LOG( OPERATION, ERR, 
1349                         "send_search_reference: conn %lu noreferrals control in (%s).\n",
1350                         op->o_connid, e->e_dn, 0 );
1351 #else
1352                 Debug( LDAP_DEBUG_ANY,
1353                         "send_search_reference: noreferrals control in (%s)\n", 
1354                         e->e_dn, 0, 0 );
1355 #endif
1356
1357                 return( 0 );
1358         }
1359
1360         if( refs == NULL ) {
1361 #ifdef NEW_LOGGING
1362                 LDAP_LOG( OPERATION, ERR, 
1363                         "send_search_reference: conn %lu null ref in (%s).\n",
1364                         op->o_connid, e ? e->e_dn : "(null)", 0 );
1365 #else
1366                 Debug( LDAP_DEBUG_ANY,
1367                         "send_search_reference: null ref in (%s)\n", 
1368                         e ? e->e_dn : "(null)", 0, 0 );
1369 #endif
1370
1371                 return( 1 );
1372         }
1373
1374         if( op->o_protocol < LDAP_VERSION3 ) {
1375                 /* save the references for the result */
1376                 if( refs[0].bv_val != NULL ) {
1377                         if( value_add( v2refs, refs ) )
1378                                 return LDAP_OTHER;
1379                 }
1380                 return 0;
1381         }
1382
1383 #ifdef LDAP_CONNECTIONLESS
1384         if (conn->c_is_udp)
1385                 ber = op->o_res_ber;
1386         else
1387 #endif
1388         ber_init_w_nullc( ber, LBER_USE_DER );
1389
1390         rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid,
1391                 LDAP_RES_SEARCH_REFERENCE, refs );
1392
1393         if( rc != -1 && ctrls != NULL ) {
1394                 rc = send_ldap_controls( ber, ctrls );
1395         }
1396
1397         if( rc != -1 ) {
1398                 rc = ber_printf( ber, /*"{"*/ "N}", op->o_msgid,
1399                         LDAP_RES_SEARCH_REFERENCE, refs );
1400         }
1401
1402         if ( rc == -1 ) {
1403 #ifdef NEW_LOGGING
1404                 LDAP_LOG( OPERATION, ERR, 
1405                         "send_search_reference: conn %lu        "
1406                         "ber_printf failed.\n", op->o_connid, 0, 0 );
1407 #else
1408                 Debug( LDAP_DEBUG_ANY,
1409                         "send_search_reference: ber_printf failed\n", 0, 0, 0 );
1410 #endif
1411
1412 #ifdef LDAP_CONNECTIONLESS
1413                 if (conn->c_is_udp == 0)
1414 #endif
1415                 ber_free_buf( ber );
1416                 send_ldap_result( conn, op, LDAP_OTHER,
1417                         NULL, "encode DN error", NULL, NULL );
1418                 return -1;
1419         }
1420
1421 #ifdef LDAP_CONNECTIONLESS
1422         if (conn->c_is_udp == 0) {
1423 #endif
1424         bytes = op->o_noop ? 0 : send_ldap_ber( conn, ber );
1425         ber_free_buf( ber );
1426
1427         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1428         num_bytes_sent += bytes;
1429         num_refs_sent++;
1430         num_pdu_sent++;
1431         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1432 #ifdef LDAP_CONNECTIONLESS
1433         }
1434 #endif
1435
1436         Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu REF dn=\"%s\"\n",
1437                 conn->c_connid, op->o_opid, e ? e->e_dn : "(null)", 0, 0 );
1438
1439 #ifdef NEW_LOGGING
1440         LDAP_LOG( OPERATION, ENTRY, 
1441                 "send_search_reference: conn %lu exit.\n", op->o_connid, 0, 0 );
1442 #else
1443         Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 );
1444 #endif
1445
1446         return 0;
1447 }
1448
1449
1450 int
1451 str2result(
1452     char        *s,
1453     int         *code,
1454     char        **matched,
1455     char        **info
1456 )
1457 {
1458         int     rc;
1459         char    *c;
1460
1461         *code = LDAP_SUCCESS;
1462         *matched = NULL;
1463         *info = NULL;
1464
1465         if ( strncasecmp( s, "RESULT", 6 ) != 0 ) {
1466 #ifdef NEW_LOGGING
1467                 LDAP_LOG( OPERATION, INFO, 
1468                         "str2result: (%s), expecting \"RESULT\"\n", s, 0, 0 );
1469 #else
1470                 Debug( LDAP_DEBUG_ANY, "str2result (%s) expecting \"RESULT\"\n",
1471                     s, 0, 0 );
1472 #endif
1473
1474                 return( -1 );
1475         }
1476
1477         rc = 0;
1478         while ( (s = strchr( s, '\n' )) != NULL ) {
1479                 *s++ = '\0';
1480                 if ( *s == '\0' ) {
1481                         break;
1482                 }
1483                 if ( (c = strchr( s, ':' )) != NULL ) {
1484                         c++;
1485                 }
1486
1487                 if ( strncasecmp( s, "code", 4 ) == 0 ) {
1488                         if ( c != NULL ) {
1489                                 *code = atoi( c );
1490                         }
1491                 } else if ( strncasecmp( s, "matched", 7 ) == 0 ) {
1492                         if ( c != NULL ) {
1493                                 *matched = c;
1494                         }
1495                 } else if ( strncasecmp( s, "info", 4 ) == 0 ) {
1496                         if ( c != NULL ) {
1497                                 *info = c;
1498                         }
1499                 } else {
1500 #ifdef NEW_LOGGING
1501                         LDAP_LOG( OPERATION, INFO, "str2result: (%s) unknown.\n", s, 0, 0 );
1502 #else
1503                         Debug( LDAP_DEBUG_ANY, "str2result (%s) unknown\n",
1504                             s, 0, 0 );
1505 #endif
1506
1507                         rc = -1;
1508                 }
1509         }
1510
1511         return( rc );
1512 }