]> git.sur5r.net Git - openldap/blob - servers/slapd/result.c
341040f8f4f8c2756a0b7b006bc63403027d41ed
[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
690         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
691
692         /* a_flags: array of flags telling if the i-th element will be
693          *          returned or filtered out
694          * e_flags: array of a_flags
695          */
696         char **e_flags = NULL;
697
698         if (op->o_callback && op->o_callback->sc_sendentry) {
699                 return op->o_callback->sc_sendentry( be, conn, op, e, attrs,
700                         attrsonly, ctrls );
701         }
702
703 #ifdef NEW_LOGGING
704         LDAP_LOG( OPERATION, ENTRY, 
705                 "send_search_entry: conn %lu    dn=\"%s\"%s\n",
706                 op->o_connid, e->e_dn, attrsonly ? " (attrsOnly)" : "" );
707 #else
708         Debug( LDAP_DEBUG_TRACE,
709                 "=> send_search_entry: dn=\"%s\"%s\n",
710                 e->e_dn, attrsonly ? " (attrsOnly)" : "", 0 );
711 #endif
712
713         if ( ! access_allowed( be, conn, op, e,
714                 ad_entry, NULL, ACL_READ, NULL ) )
715         {
716 #ifdef NEW_LOGGING
717                 LDAP_LOG( ACL, INFO, 
718                         "send_search_entry: conn %lu access to entry (%s) not allowed\n", 
719                         op->o_connid, e->e_dn, 0 );
720 #else
721                 Debug( LDAP_DEBUG_ACL,
722                         "send_search_entry: access to entry not allowed\n",
723                     0, 0, 0 );
724 #endif
725
726                 return( 1 );
727         }
728
729         edn = e->e_ndn;
730
731         ber_init_w_nullc( ber, LBER_USE_DER );
732
733 #ifdef LDAP_CONNECTIONLESS
734         if (conn->c_is_udp) {
735             rc = ber_write(ber,
736                         (char *)&op->o_peeraddr, sizeof(struct sockaddr), 0);
737             if (rc != sizeof(struct sockaddr)) {
738 #ifdef NEW_LOGGING
739                         LDAP_LOG( OPERATION, ERR, 
740                                 "send_search_entry: conn %lu  ber_write failed\n",
741                                 conn ? conn->c_connid : 0, 0, 0 );
742 #else
743                         Debug( LDAP_DEBUG_ANY, "ber_write failed\n", 0, 0, 0 );
744 #endif
745                         ber_free_buf( ber );
746                         return( 1 );
747             }
748         }
749         if (conn->c_is_udp && op->o_protocol == LDAP_VERSION2) {
750             rc = ber_printf( ber, "{is{t{O{" /*}}}*/,
751                 op->o_msgid, "", LDAP_RES_SEARCH_ENTRY, &e->e_name );
752         } else
753 #endif /* LDAP_CONNECTIONLESS */
754         {
755             rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
756                 LDAP_RES_SEARCH_ENTRY, &e->e_name );
757         }
758
759         if ( rc == -1 ) {
760 #ifdef NEW_LOGGING
761                 LDAP_LOG( OPERATION, ERR, 
762                         "send_search_entry: conn %lu  ber_printf failed\n", 
763                         op->o_connid, 0, 0 );
764 #else
765                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
766 #endif
767
768                 ber_free_buf( ber );
769                 send_ldap_result( conn, op, LDAP_OTHER,
770                     NULL, "encoding DN error", NULL, NULL );
771                 goto error_return;
772         }
773
774         /* check for special all user attributes ("*") type */
775         userattrs = ( attrs == NULL ) ? 1
776                 : an_find( attrs, &AllUser );
777
778         /* check for special all operational attributes ("+") type */
779         opattrs = ( attrs == NULL ) ? 0
780                 : an_find( attrs, &AllOper );
781
782         /* create an array of arrays of flags. Each flag corresponds
783          * to particular value of attribute and equals 1 if value matches
784          * to ValuesReturnFilter or 0 if not
785          */     
786         if ( op->vrFilter != NULL ) {
787                 int     k = 0;
788                 size_t  size;
789
790                 for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
791                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
792                 }
793
794                 size = i * sizeof(char *) + k;
795                 if ( size > 0 ) {
796                         char    *a_flags;
797                         e_flags = SLAP_CALLOC ( 1, i * sizeof(char *) + k );
798                         if( e_flags == NULL ) {
799 #ifdef NEW_LOGGING
800                                 LDAP_LOG( OPERATION, ERR, 
801                                         "send_search_entry: conn %lu SLAP_CALLOC failed\n",
802                                         conn ? conn->c_connid : 0, 0, 0 );
803 #else
804                         Debug( LDAP_DEBUG_ANY, 
805                                         "send_search_entry: SLAP_CALLOC failed\n", 0, 0, 0 );
806 #endif
807                                 ber_free( ber, 1 );
808         
809                                 send_ldap_result( conn, op, LDAP_OTHER,
810                                         NULL, "memory error", 
811                                         NULL, NULL );
812                                 goto error_return;
813                         }
814                         a_flags = (char *)(e_flags + i);
815                         memset( a_flags, 0, k );
816                         for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
817                                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
818                                 e_flags[i] = a_flags;
819                                 a_flags += j;
820                         }
821         
822                         rc = filter_matched_values(be, conn, op, e->e_attrs, &e_flags) ; 
823                         if ( rc == -1 ) {
824 #ifdef NEW_LOGGING
825                                 LDAP_LOG( OPERATION, ERR, 
826                                         "send_search_entry: conn %lu matched values filtering failed\n",
827                                         conn ? conn->c_connid : 0, 0, 0 );
828 #else
829                         Debug( LDAP_DEBUG_ANY,
830                                         "matched values filtering failed\n", 0, 0, 0 );
831 #endif
832                                 ber_free( ber, 1 );
833         
834                                 send_ldap_result( conn, op, LDAP_OTHER,
835                                         NULL, "matched values filtering error", 
836                                         NULL, NULL );
837                                 goto error_return;
838                         }
839                 }
840         }
841
842         for ( a = e->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) {
843                 AttributeDescription *desc = a->a_desc;
844
845                 if ( attrs == NULL ) {
846                         /* all attrs request, skip operational attributes */
847                         if( is_at_operational( desc->ad_type ) ) {
848                                 continue;
849                         }
850
851                 } else {
852                         /* specific attrs requested */
853                         if ( is_at_operational( desc->ad_type ) ) {
854                                 if( !opattrs && !ad_inlist( desc, attrs ) ) {
855                                         continue;
856                                 }
857
858                         } else {
859                                 if (!userattrs && !ad_inlist( desc, attrs ) ) {
860                                         continue;
861                                 }
862                         }
863                 }
864
865                 if ( ! access_allowed( be, conn, op, e, desc, NULL,
866                         ACL_READ, &acl_state ) )
867                 {
868 #ifdef NEW_LOGGING
869                         LDAP_LOG( ACL, INFO, 
870                                 "send_search_entry: conn %lu  access to attribute %s not "
871                                 "allowed\n", op->o_connid, desc->ad_cname.bv_val, 0 );
872 #else
873                         Debug( LDAP_DEBUG_ACL, "acl: "
874                                 "access to attribute %s not allowed\n",
875                             desc->ad_cname.bv_val, 0, 0 );
876 #endif
877                         continue;
878                 }
879
880                 if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
881 #ifdef NEW_LOGGING
882                         LDAP_LOG( OPERATION, ERR, 
883                                 "send_search_entry: conn %lu  ber_printf failed\n", 
884                                 op->o_connid, 0, 0 );
885 #else
886                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
887 #endif
888
889                         ber_free_buf( ber );
890                         send_ldap_result( conn, op, LDAP_OTHER,
891                             NULL, "encoding description error", NULL, NULL );
892                         goto error_return;
893                 }
894
895                 if ( ! attrsonly ) {
896                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
897                                 if ( ! access_allowed( be, conn, op, e,
898                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
899                                 {
900 #ifdef NEW_LOGGING
901                                         LDAP_LOG( ACL, INFO, 
902                                                 "send_search_entry: conn %lu "
903                                                 "access to attribute %s, value %d not allowed\n",
904                                                 op->o_connid, desc->ad_cname.bv_val, i );
905 #else
906                                         Debug( LDAP_DEBUG_ACL,
907                                                 "acl: access to attribute %s, "
908                                                 "value %d not allowed\n",
909                                                 desc->ad_cname.bv_val, i, 0 );
910 #endif
911
912                                         continue;
913                                 }
914
915                                 if ( op->vrFilter && e_flags[j][i] == 0 ){
916                                         continue;
917                                 }
918
919                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
920 #ifdef NEW_LOGGING
921                                         LDAP_LOG( OPERATION, ERR, 
922                                                 "send_search_entry: conn %lu  "
923                                                 "ber_printf failed.\n", op->o_connid, 0, 0 );
924 #else
925                                         Debug( LDAP_DEBUG_ANY,
926                                             "ber_printf failed\n", 0, 0, 0 );
927 #endif
928
929                                         ber_free_buf( ber );
930                                         send_ldap_result( conn, op, LDAP_OTHER,
931                                                 NULL, "encoding values error",
932                                                 NULL, NULL );
933                                         goto error_return;
934                                 }
935                         }
936                 }
937
938                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
939 #ifdef NEW_LOGGING
940                         LDAP_LOG( OPERATION, ERR, 
941                                 "send_search_entry: conn %lu ber_printf failed\n", 
942                                 op->o_connid, 0, 0 );
943 #else
944                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
945 #endif
946
947                         ber_free_buf( ber );
948                         send_ldap_result( conn, op, LDAP_OTHER,
949                             NULL, "encode end error", NULL, NULL );
950                         goto error_return;
951                 }
952         }
953
954         /* eventually will loop through generated operational attributes */
955         /* only have subschemaSubentry implemented */
956         aa = backend_operational( be, conn, op, e, attrs, opattrs );
957
958         if ( aa != NULL && op->vrFilter != NULL ) {
959                 int     k = 0;
960                 size_t  size;
961
962                 for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
963                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
964                 }
965
966                 size = i * sizeof(char *) + k;
967                 if ( size > 0 ) {
968                         char    *a_flags, **tmp;
969                 
970                         /*
971                          * Reuse previous memory - we likely need less space
972                          * for operational attributes
973                          */
974                         tmp = SLAP_REALLOC ( e_flags, i * sizeof(char *) + k );
975                         if ( tmp == NULL ) {
976 #ifdef NEW_LOGGING
977                                 LDAP_LOG( OPERATION, ERR, 
978                                         "send_search_entry: conn %lu "
979                                         "not enough memory "
980                                         "for matched values filtering\n", 
981                                         conn ? conn->c_connid : 0, 0, 0);
982 #else
983                                 Debug( LDAP_DEBUG_ANY,
984                                         "send_search_entry: conn %lu "
985                                         "not enough memory "
986                                         "for matched values filtering\n",
987                                         conn ? conn->c_connid : 0, 0, 0 );
988 #endif
989                                 ber_free( ber, 1 );
990         
991                                 send_ldap_result( conn, op, LDAP_NO_MEMORY,
992                                         NULL, NULL, NULL, NULL );
993                                 goto error_return;
994                         }
995                         e_flags = tmp;
996                         a_flags = (char *)(e_flags + i);
997                         memset( a_flags, 0, k );
998                         for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
999                                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
1000                                 e_flags[i] = a_flags;
1001                                 a_flags += j;
1002                         }
1003                         rc = filter_matched_values(be, conn, op, aa, &e_flags) ; 
1004                     
1005                         if ( rc == -1 ) {
1006 #ifdef NEW_LOGGING
1007                                 LDAP_LOG( OPERATION, ERR, 
1008                                         "send_search_entry: conn %lu "
1009                                         "matched values filtering failed\n", 
1010                                         conn ? conn->c_connid : 0, 0, 0);
1011 #else
1012                                 Debug( LDAP_DEBUG_ANY,
1013                                         "matched values filtering failed\n", 0, 0, 0 );
1014 #endif
1015                                 ber_free( ber, 1 );
1016         
1017                                 send_ldap_result( conn, op, LDAP_OTHER,
1018                                         NULL, "matched values filtering error", 
1019                                         NULL, NULL );
1020                                 goto error_return;
1021                         }
1022                 }
1023         }
1024
1025         for (a = aa, j=0; a != NULL; a = a->a_next, j++ ) {
1026                 AttributeDescription *desc = a->a_desc;
1027
1028                 if ( attrs == NULL ) {
1029                         /* all attrs request, skip operational attributes */
1030                         if( is_at_operational( desc->ad_type ) ) {
1031                                 continue;
1032                         }
1033
1034                 } else {
1035                         /* specific attrs requested */
1036                         if( is_at_operational( desc->ad_type ) ) {
1037                                 if( !opattrs && !ad_inlist( desc, attrs ) ) {
1038                                         continue;
1039                                 }
1040                         } else {
1041                                 if (!userattrs && !ad_inlist( desc, attrs ) )
1042                                 {
1043                                         continue;
1044                                 }
1045                         }
1046                 }
1047
1048                 if ( ! access_allowed( be, conn, op, e, desc, NULL,
1049                         ACL_READ, &acl_state ) )
1050                 {
1051 #ifdef NEW_LOGGING
1052                         LDAP_LOG( ACL, INFO, 
1053                                 "send_search_entry: conn %lu "
1054                                 "access to attribute %s not allowed\n",
1055                                 op->o_connid, desc->ad_cname.bv_val, 0 );
1056 #else
1057                         Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s "
1058                                         "not allowed\n",
1059                                         desc->ad_cname.bv_val, 0, 0 );
1060 #endif
1061
1062                         continue;
1063                 }
1064
1065                 rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname );
1066                 if ( rc == -1 ) {
1067 #ifdef NEW_LOGGING
1068                         LDAP_LOG( OPERATION, ERR, 
1069                                 "send_search_entry: conn %lu  "
1070                                 "ber_printf failed\n", op->o_connid, 0, 0 );
1071 #else
1072                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1073 #endif
1074
1075                         ber_free_buf( ber );
1076                         send_ldap_result( conn, op, LDAP_OTHER,
1077                             NULL, "encoding description error", NULL, NULL );
1078
1079                         attrs_free( aa );
1080                         goto error_return;
1081                 }
1082
1083                 if ( ! attrsonly ) {
1084                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
1085                                 if ( ! access_allowed( be, conn, op, e,
1086                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
1087                                 {
1088 #ifdef NEW_LOGGING
1089                                         LDAP_LOG( ACL, INFO, 
1090                                                 "send_search_entry: conn %lu "
1091                                                 "access to %s, value %d not allowed\n",
1092                                                 op->o_connid, desc->ad_cname.bv_val, i );
1093 #else
1094                                         Debug( LDAP_DEBUG_ACL,
1095                                                 "acl: access to attribute %s, "
1096                                                 "value %d not allowed\n",
1097                                                 desc->ad_cname.bv_val, i, 0 );
1098 #endif
1099
1100                                         continue;
1101                                 }
1102
1103                                 if ( op->vrFilter && e_flags[j][i] == 0 ){
1104                                         continue;
1105                                 }
1106
1107                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
1108 #ifdef NEW_LOGGING
1109                                         LDAP_LOG( OPERATION, ERR, 
1110                                                 "send_search_entry: conn %lu  ber_printf failed\n", 
1111                                                 op->o_connid, 0, 0 );
1112 #else
1113                                         Debug( LDAP_DEBUG_ANY,
1114                                             "ber_printf failed\n", 0, 0, 0 );
1115 #endif
1116
1117                                         ber_free_buf( ber );
1118                                         send_ldap_result( conn, op, LDAP_OTHER,
1119                                                 NULL, "encoding values error", 
1120                                                 NULL, NULL );
1121
1122                                         attrs_free( aa );
1123                                         goto error_return;
1124                                 }
1125                         }
1126                 }
1127
1128                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
1129 #ifdef NEW_LOGGING
1130                         LDAP_LOG( OPERATION, ERR, 
1131                                 "send_search_entry: conn %lu  ber_printf failed\n",
1132                                 op->o_connid, 0, 0 );
1133 #else
1134                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1135 #endif
1136
1137                         ber_free_buf( ber );
1138                         send_ldap_result( conn, op, LDAP_OTHER,
1139                             NULL, "encode end error", NULL, NULL );
1140
1141                         attrs_free( aa );
1142                         goto error_return;
1143                 }
1144         }
1145
1146         /* free e_flags */
1147         if ( e_flags ) {
1148                 free( e_flags );
1149                 e_flags = NULL;
1150         }
1151
1152         attrs_free( aa );
1153         rc = ber_printf( ber, /*{{*/ "}N}" );
1154
1155         if( rc != -1 && ctrls != NULL ) {
1156                 rc = send_ldap_controls( ber, ctrls );
1157         }
1158
1159         if( rc != -1 ) {
1160                 rc = ber_printf( ber, /*{*/ "N}" );
1161         }
1162
1163 #ifdef LDAP_CONNECTIONLESS
1164         if (conn->c_is_udp && op->o_protocol == LDAP_VERSION2 && rc != -1) {
1165                 rc = ber_printf( ber, "}" );
1166         }
1167 #endif
1168         if ( rc == -1 ) {
1169 #ifdef NEW_LOGGING
1170                 LDAP_LOG( OPERATION, ERR, 
1171                         "send_search_entry: conn %lu ber_printf failed\n", 
1172                         op->o_connid, 0, 0 );
1173 #else
1174                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1175 #endif
1176
1177                 ber_free_buf( ber );
1178                 send_ldap_result( conn, op, LDAP_OTHER,
1179                         NULL, "encode entry end error", NULL, NULL );
1180                 return( 1 );
1181         }
1182
1183         bytes = op->o_noop ? 0 : send_ldap_ber( conn, ber );
1184         ber_free_buf( ber );
1185
1186         if ( bytes < 0 ) {
1187 #ifdef NEW_LOGGING
1188                 LDAP_LOG( OPERATION, ERR, 
1189                            "send_search_entry: conn %lu  ber write failed.\n", 
1190                            op->o_connid, 0, 0 );
1191 #else
1192                 Debug( LDAP_DEBUG_ANY,
1193                         "send_search_entry: ber write failed\n",
1194                         0, 0, 0 );
1195 #endif
1196
1197                 return -1;
1198         }
1199
1200         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1201         num_bytes_sent += bytes;
1202         num_entries_sent++;
1203         num_pdu_sent++;
1204         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1205
1206         Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu ENTRY dn=\"%s\"\n",
1207             conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
1208
1209 #ifdef NEW_LOGGING
1210         LDAP_LOG( OPERATION, ENTRY, 
1211                 "send_search_entry: conn %lu exit.\n", op->o_connid, 0, 0 );
1212 #else
1213         Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
1214 #endif
1215
1216         rc = 0;
1217
1218 error_return:;
1219         if ( e_flags ) free( e_flags );
1220         return( rc );
1221 }
1222
1223 int
1224 slap_send_search_reference(
1225     Backend     *be,
1226     Connection  *conn,
1227     Operation   *op,
1228     Entry       *e,
1229         BerVarray refs,
1230         LDAPControl **ctrls,
1231     BerVarray *v2refs
1232 )
1233 {
1234         char berbuf[LBER_ELEMENT_SIZEOF];
1235         BerElement      *ber = (BerElement *)berbuf;
1236         int rc;
1237         int bytes;
1238
1239         AttributeDescription *ad_ref = slap_schema.si_ad_ref;
1240         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
1241
1242 #ifdef NEW_LOGGING
1243         LDAP_LOG( OPERATION, ENTRY, 
1244                 "send_search_reference: conn %lu  dn=\"%s\"\n", 
1245                 op->o_connid, e ? e->e_dn : "(null)", 0 );
1246 #else
1247         Debug( LDAP_DEBUG_TRACE,
1248                 "=> send_search_reference: dn=\"%s\"\n",
1249                 e ? e->e_dn : "(null)", 0, 0 );
1250 #endif
1251
1252
1253         if (  e && ! access_allowed( be, conn, op, e,
1254                 ad_entry, NULL, ACL_READ, NULL ) )
1255         {
1256 #ifdef NEW_LOGGING
1257                 LDAP_LOG( ACL, INFO, 
1258                         "send_search_reference: conn %lu        "
1259                         "access to entry %s not allowed\n",
1260                         op->o_connid, e->e_dn, 0 );
1261 #else
1262                 Debug( LDAP_DEBUG_ACL,
1263                         "send_search_reference: access to entry not allowed\n",
1264                     0, 0, 0 );
1265 #endif
1266
1267                 return( 1 );
1268         }
1269
1270         if ( e && ! access_allowed( be, conn, op, e,
1271                 ad_ref, NULL, ACL_READ, NULL ) )
1272         {
1273 #ifdef NEW_LOGGING
1274                 LDAP_LOG( ACL, INFO, 
1275                         "send_search_reference: conn %lu access "
1276                         "to reference not allowed.\n", op->o_connid, 0, 0 );
1277 #else
1278                 Debug( LDAP_DEBUG_ACL,
1279                         "send_search_reference: access "
1280                         "to reference not allowed\n",
1281                     0, 0, 0 );
1282 #endif
1283
1284                 return( 1 );
1285         }
1286
1287         if( refs == NULL ) {
1288 #ifdef NEW_LOGGING
1289                 LDAP_LOG( OPERATION, ERR, 
1290                         "send_search_reference: conn %lu null ref in (%s).\n",
1291                         op->o_connid, e ? e->e_dn : "(null)", 0 );
1292 #else
1293                 Debug( LDAP_DEBUG_ANY,
1294                         "send_search_reference: null ref in (%s)\n", 
1295                         e ? e->e_dn : "(null)", 0, 0 );
1296 #endif
1297
1298                 return( 1 );
1299         }
1300
1301         if( op->o_protocol < LDAP_VERSION3 ) {
1302                 /* save the references for the result */
1303                 if( refs[0].bv_val != NULL ) {
1304                         if( value_add( v2refs, refs ) )
1305                                 return LDAP_OTHER;
1306                 }
1307                 return 0;
1308         }
1309
1310         ber_init_w_nullc( ber, LBER_USE_DER );
1311
1312         rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid,
1313                 LDAP_RES_SEARCH_REFERENCE, refs );
1314
1315         if( rc != -1 && ctrls != NULL ) {
1316                 rc = send_ldap_controls( ber, ctrls );
1317         }
1318
1319         if( rc != -1 ) {
1320                 rc = ber_printf( ber, /*"{"*/ "N}", op->o_msgid,
1321                         LDAP_RES_SEARCH_REFERENCE, refs );
1322         }
1323
1324         if ( rc == -1 ) {
1325 #ifdef NEW_LOGGING
1326                 LDAP_LOG( OPERATION, ERR, 
1327                         "send_search_reference: conn %lu        "
1328                         "ber_printf failed.\n", op->o_connid, 0, 0 );
1329 #else
1330                 Debug( LDAP_DEBUG_ANY,
1331                         "send_search_reference: ber_printf failed\n", 0, 0, 0 );
1332 #endif
1333
1334                 ber_free_buf( ber );
1335                 send_ldap_result( conn, op, LDAP_OTHER,
1336                         NULL, "encode DN error", NULL, NULL );
1337                 return -1;
1338         }
1339
1340         bytes = op->o_noop ? 0 : send_ldap_ber( conn, ber );
1341         ber_free_buf( ber );
1342
1343         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1344         num_bytes_sent += bytes;
1345         num_refs_sent++;
1346         num_pdu_sent++;
1347         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1348
1349         Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu REF dn=\"%s\"\n",
1350                 conn->c_connid, op->o_opid, e ? e->e_dn : "(null)", 0, 0 );
1351
1352 #ifdef NEW_LOGGING
1353         LDAP_LOG( OPERATION, ENTRY, 
1354                 "send_search_reference: conn %lu exit.\n", op->o_connid, 0, 0 );
1355 #else
1356         Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 );
1357 #endif
1358
1359         return 0;
1360 }
1361
1362
1363 int
1364 str2result(
1365     char        *s,
1366     int         *code,
1367     char        **matched,
1368     char        **info
1369 )
1370 {
1371         int     rc;
1372         char    *c;
1373
1374         *code = LDAP_SUCCESS;
1375         *matched = NULL;
1376         *info = NULL;
1377
1378         if ( strncasecmp( s, "RESULT", 6 ) != 0 ) {
1379 #ifdef NEW_LOGGING
1380                 LDAP_LOG( OPERATION, INFO, 
1381                         "str2result: (%s), expecting \"RESULT\"\n", s, 0, 0 );
1382 #else
1383                 Debug( LDAP_DEBUG_ANY, "str2result (%s) expecting \"RESULT\"\n",
1384                     s, 0, 0 );
1385 #endif
1386
1387                 return( -1 );
1388         }
1389
1390         rc = 0;
1391         while ( (s = strchr( s, '\n' )) != NULL ) {
1392                 *s++ = '\0';
1393                 if ( *s == '\0' ) {
1394                         break;
1395                 }
1396                 if ( (c = strchr( s, ':' )) != NULL ) {
1397                         c++;
1398                 }
1399
1400                 if ( strncasecmp( s, "code", 4 ) == 0 ) {
1401                         if ( c != NULL ) {
1402                                 *code = atoi( c );
1403                         }
1404                 } else if ( strncasecmp( s, "matched", 7 ) == 0 ) {
1405                         if ( c != NULL ) {
1406                                 *matched = c;
1407                         }
1408                 } else if ( strncasecmp( s, "info", 4 ) == 0 ) {
1409                         if ( c != NULL ) {
1410                                 *info = c;
1411                         }
1412                 } else {
1413 #ifdef NEW_LOGGING
1414                         LDAP_LOG( OPERATION, INFO, "str2result: (%s) unknown.\n", s, 0, 0 );
1415 #else
1416                         Debug( LDAP_DEBUG_ANY, "str2result (%s) unknown\n",
1417                             s, 0, 0 );
1418 #endif
1419
1420                         rc = -1;
1421                 }
1422         }
1423
1424         return( rc );
1425 }