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