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