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