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