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