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