]> git.sur5r.net Git - openldap/blob - servers/ldapd/search.c
Remove extern declarations of library functions from source.c.
[openldap] / servers / ldapd / search.c
1 /*
2  * Copyright (c) 1990 Regents of the University of Michigan.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of Michigan at Ann Arbor. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12
13 #include "portable.h"
14
15 #include <stdio.h>
16
17 #include <ac/socket.h>
18 #include <ac/string.h>
19
20 #include <quipu/commonarg.h>
21 #include <quipu/attrvalue.h>
22 #include <quipu/ds_error.h>
23 #include <quipu/ds_search.h>
24 #include <quipu/dap2.h>
25 #include <quipu/dua.h>
26
27 #include "lber.h"
28 #include "../../libraries/liblber/lber-int.h"   /* get struct berelement */
29 #include "ldap.h"
30 #include "common.h"
31
32 static int      get_filter( BerElement *ber, Filter *filt );
33 static int      get_filter_list( BerElement *ber, Filter f );
34 static int      get_substring_filter( BerElement *ber, Filter f );
35
36 #ifdef LDAP_COMPAT
37 #define SEARCHRESTAG    (ldap_compat == 20 ? OLD_LDAP_RES_SEARCH_RESULT : LDAP_RES_SEARCH_RESULT)
38 #else
39 #define SEARCHRESTAG    LDAP_RES_SEARCH_RESULT
40 #endif
41
42 int
43 do_search(
44     Sockbuf     *clientsb,
45     struct msg  *m,
46     BerElement  *ber
47 )
48 {
49         int                     rc, err;
50         int                     deref, attrsonly;
51         int                     sizelimit, timelimit;
52         char                    *base;
53         char                    **attrs;
54         struct ds_search_arg    sa;
55         static CommonArgs       common = default_common_args;
56
57         Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
58
59         /*
60          * Parse the search request.  It looks like this:
61          *      SearchRequest := [APPLICATION 3] SEQUENCE {
62          *              baseObject      DistinguishedName,
63          *              scope           ENUMERATED {
64          *                      baseObject      (0),
65          *                      singleLevel     (1),
66          *                      wholeSubtree    (2)
67          *              },
68          *              derefAliases    ENUMERATED {
69          *                      neverDerefaliases       (0),
70          *                      derefInSearching        (1),
71          *                      derefFindingBaseObj     (2),
72          *                      alwaysDerefAliases      (3)
73          *              },
74          *              sizelimit       INTEGER (0 .. 65535),
75          *              timelimit       INTEGER (0 .. 65535),
76          *              attrsOnly       BOOLEAN,
77          *              filter          Filter,
78          *              attributes      SEQUENCE OF AttributeType
79          *      }
80          */
81
82 #if ISODEPACKAGE == IC
83 #if ICRELEASE > 2
84         DAS_SearchArgument_INIT( &sa );
85 #endif
86 #endif
87
88         if ( ber_scanf( ber, "{aiiiib", &base, &sa.sra_subset, &deref,
89             &sizelimit, &timelimit, &attrsonly ) == LBER_ERROR ) {
90                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
91                     LDAP_PROTOCOL_ERROR, NULL, "" );
92                 return( 0 );
93         }
94
95         sa.sra_baseobject = ldap_str2dn( base );
96         if ( sa.sra_baseobject == NULLDN && *base != '\0' ) {
97                 free( base );
98                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
99                     LDAP_INVALID_DN_SYNTAX, NULL, "" );
100                 return( 0 );
101         }
102         free( base );
103
104         sa.sra_common = common; /* struct copy */
105         sa.sra_searchaliases = (deref == LDAP_DEREF_SEARCHING ||
106             deref == LDAP_DEREF_ALWAYS);
107         if ( deref == LDAP_DEREF_NEVER || deref == LDAP_DEREF_SEARCHING )
108                 sa.sra_common.ca_servicecontrol.svc_options |=
109                     SVC_OPT_DONTDEREFERENCEALIAS;
110
111         sa.sra_common.ca_servicecontrol.svc_sizelimit = (sizelimit == 0 ?
112             SVC_NOSIZELIMIT : sizelimit);
113
114         sa.sra_common.ca_servicecontrol.svc_timelimit = (timelimit == 0 ?
115             SVC_NOTIMELIMIT : timelimit);
116
117         sa.sra_eis.eis_infotypes = (attrsonly ? EIS_ATTRIBUTETYPESONLY :
118             EIS_ATTRIBUTESANDVALUES);
119
120         /* search filter */
121         if ( (err = get_filter( ber, &sa.sra_filter )) != 0 ) {
122                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
123                     err, NULL, "Bad search filter" );
124                 return( 0 );
125         }
126
127 #ifdef LDAP_DEBUG
128         if ( ldap_debug & LDAP_DEBUG_ARGS ) {
129                 PS      ps;
130
131                 ps = ps_alloc( std_open );
132                 std_setup( ps, stderr );
133                 ps_print( ps, "Filter: " );
134                 fi_print( ps, sa.sra_filter, EDBOUT );
135                 ps_print( ps, "\n" );
136                 ps_free( ps );
137         }
138 #endif
139
140         /* attrs to return */
141         attrs = NULL;
142         if ( ber_scanf( ber, "{v}}", &attrs ) == LBER_ERROR ) {
143                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
144                     LDAP_PROTOCOL_ERROR, NULL, "" );
145                 return( 0 );
146         }
147         sa.sra_eis.eis_select = NULLATTR;
148         if ( attrs == NULL ) {
149                 sa.sra_eis.eis_allattributes = 1;
150         } else {
151                 Attr_Sequence   as;
152                 int             i;
153
154                 sa.sra_eis.eis_allattributes = 0;
155                 for ( i = 0; attrs[i] != NULL; i++ ) {
156                         AttributeType   type;
157
158                         if ( (type = AttrT_new( attrs[i] )) == NULLAttrT ) {
159                                 Debug( LDAP_DEBUG_TRACE, "unknown attr (%s)\n",
160                                     attrs[i], 0, 0 );
161                                 continue;
162                         }
163
164                         as = as_comp_alloc();
165                         as->attr_type = type;
166                         as->attr_acl = NULLACL_INFO;
167                         as->attr_link = NULLATTR;
168                         as->attr_value = NULLAV;
169
170                         sa.sra_eis.eis_select = as_merge( as,
171                             sa.sra_eis.eis_select );
172                 }
173
174                 /* complain only if we know about none of the attrs */
175                 if ( sa.sra_eis.eis_select == NULLATTR ) {
176                         send_ldap_msgresult( clientsb, SEARCHRESTAG,
177                             m, LDAP_UNDEFINED_TYPE, NULL, attrs[0] );
178                         charlist_free( attrs );
179                         return( 0 );
180                 }
181
182                 charlist_free( attrs );
183         }
184
185         rc = initiate_dap_operation( OP_SEARCH, m, &sa );
186
187 #ifdef LDAP_CONNECTIONLESS
188         if (  m->m_cldap )
189                 m->m_searchbase = sa.sra_baseobject;
190         else
191 #endif /* LDAP_CONNECTIONLESS */
192                 dn_free( sa.sra_baseobject );
193
194         filter_free( sa.sra_filter );
195         as_free( sa.sra_eis.eis_select );
196
197         if ( rc != 0 ) {
198                 send_ldap_msgresult( clientsb, SEARCHRESTAG, m,
199                     rc, NULL, "" );
200                 return( 0 );
201         }
202
203         return( 1 );
204 }
205
206 static int
207 get_filter( BerElement *ber, Filter *filt )
208 {
209         unsigned long   tag, len;
210         int             err;
211         char            typestr[64];
212         Filter          f;
213
214         Debug( LDAP_DEBUG_TRACE, "get_filter\n", 0, 0, 0 );
215
216         /*
217          * A filter looks like this coming in:
218          *      Filter ::= CHOICE {
219          *              and             [0]     SET OF Filter,
220          *              or              [1]     SET OF Filter,
221          *              not             [2]     Filter,
222          *              equalityMatch   [3]     AttributeValueAssertion,
223          *              substrings      [4]     SubstringFilter,
224          *              greaterOrEqual  [5]     AttributeValueAssertion,
225          *              lessOrEqual     [6]     AttributeValueAssertion,
226          *              present         [7]     AttributeType,,
227          *              approxMatch     [8]     AttributeValueAssertion
228          *      }
229          *
230          *      SubstringFilter ::= SEQUENCE {
231          *              type               AttributeType,
232          *              SEQUENCE OF CHOICE {
233          *                      initial          [0] IA5String,
234          *                      any              [1] IA5String,
235          *                      final            [2] IA5String
236          *              }
237          *      }
238          */
239
240         f = filter_alloc();
241         *filt = f;
242         f->flt_next = NULLFILTER;
243
244         err = 0;
245         switch (tag = ber_peek_tag( ber, &len )) {
246 #ifdef LDAP_COMPAT20
247         case OLD_LDAP_FILTER_EQUALITY:
248 #endif
249         case LDAP_FILTER_EQUALITY:
250                 Debug( LDAP_DEBUG_ARGS, "EQUALITY\n", 0, 0, 0 );
251                 f->flt_type = FILTER_ITEM;
252                 f->FUITEM.fi_type = FILTERITEM_EQUALITY;
253 #ifdef LDAP_COMPAT30
254                 if ( ldap_compat == 30 )
255                         (void) ber_skip_tag( ber, &len );
256 #endif
257
258                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
259                         free( f );
260                         return( err );
261                 }
262                 break;
263
264 #ifdef LDAP_COMPAT20
265         case OLD_LDAP_FILTER_SUBSTRINGS:
266 #endif
267         case LDAP_FILTER_SUBSTRINGS:
268                 Debug( LDAP_DEBUG_ARGS, "SUBSTRINGS\n", 0, 0, 0 );
269                 err = get_substring_filter( ber, f );
270                 break;
271
272 #ifdef LDAP_COMPAT20
273         case OLD_LDAP_FILTER_GE:
274 #endif
275         case LDAP_FILTER_GE:
276                 Debug( LDAP_DEBUG_ARGS, "GE\n", 0, 0, 0 );
277                 f->flt_type = FILTER_ITEM;
278                 f->FUITEM.fi_type = FILTERITEM_GREATEROREQUAL;
279 #ifdef LDAP_COMPAT30
280                 if ( ldap_compat == 30 )
281                         (void) ber_skip_tag( ber, &len );
282 #endif
283                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
284                         free( f );
285                         return( err );
286                 }
287                 break;
288
289 #ifdef LDAP_COMPAT20
290         case OLD_LDAP_FILTER_LE:
291 #endif
292         case LDAP_FILTER_LE:
293                 Debug( LDAP_DEBUG_ARGS, "LE\n", 0, 0, 0 );
294                 f->flt_type = FILTER_ITEM;
295                 f->FUITEM.fi_type = FILTERITEM_LESSOREQUAL;
296 #ifdef LDAP_COMPAT30
297                 if ( ldap_compat == 30 )
298                         (void) ber_skip_tag( ber, &len );
299 #endif
300
301                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
302                         free( f );
303                         return( err );
304                 }
305                 break;
306
307 #ifdef LDAP_COMPAT20
308         case OLD_LDAP_FILTER_PRESENT:
309 #endif
310 #ifdef LDAP_COMPAT30
311         case LDAP_FILTER_PRESENT_30:
312 #endif
313         case LDAP_FILTER_PRESENT:
314                 Debug( LDAP_DEBUG_ARGS, "PRESENT\n", 0, 0, 0 );
315                 f->flt_type = FILTER_ITEM;
316                 f->FUITEM.fi_type = FILTERITEM_PRESENT;
317                 len = sizeof(typestr);
318 #ifdef LDAP_COMPAT30
319                 if ( ldap_compat == 30 )
320                         (void) ber_skip_tag( ber, &len );
321 #endif
322
323                 if ( ber_scanf( ber, "s", typestr, &len ) == LBER_ERROR )
324                         return( LDAP_PROTOCOL_ERROR );
325                 if ( (f->FUITEM.UNTYPE = str2AttrT( typestr )) == NULLAttrT )
326                         return( LDAP_UNDEFINED_TYPE );
327                 break;
328
329 #ifdef LDAP_COMPAT20
330         case OLD_LDAP_FILTER_APPROX:
331 #endif
332         case LDAP_FILTER_APPROX:
333                 Debug( LDAP_DEBUG_ARGS, "APPROX\n", 0, 0, 0 );
334                 f->flt_type = FILTER_ITEM;
335                 f->FUITEM.fi_type = FILTERITEM_APPROX;
336 #ifdef LDAP_COMPAT30
337                 if ( ldap_compat == 30 )
338                         (void) ber_skip_tag( ber, &len );
339 #endif
340
341                 if ( (err = get_ava( ber, &f->FUITEM.UNAVA )) != 0 ) {
342                         free( f );
343                         return( err );
344                 }
345                 break;
346
347 #ifdef LDAP_COMPAT20
348         case OLD_LDAP_FILTER_AND:
349 #endif
350         case LDAP_FILTER_AND:
351                 Debug( LDAP_DEBUG_ARGS, "AND\n", 0, 0, 0 );
352                 f->flt_type = FILTER_AND;
353                 err = get_filter_list( ber, f );
354                 break;
355
356 #ifdef LDAP_COMPAT20
357         case OLD_LDAP_FILTER_OR:
358 #endif
359         case LDAP_FILTER_OR:
360                 Debug( LDAP_DEBUG_ARGS, "OR\n", 0, 0, 0 );
361                 f->flt_type = FILTER_OR;
362                 err = get_filter_list( ber, f );
363                 break;
364
365 #ifdef LDAP_COMPAT20
366         case OLD_LDAP_FILTER_NOT:
367 #endif
368         case LDAP_FILTER_NOT:
369                 Debug( LDAP_DEBUG_ARGS, "NOT\n", 0, 0, 0 );
370                 f->flt_type = FILTER_NOT;
371                 (void) ber_skip_tag( ber, &len );
372                 err = get_filter( ber, &f->FUFILT );
373                 break;
374
375         default:
376                 Debug( LDAP_DEBUG_ANY, "unknown filter type %lu\n", tag, 0, 0 );
377                 free( f );
378                 return( LDAP_PROTOCOL_ERROR );
379                 break;
380         }
381
382         Debug( LDAP_DEBUG_TRACE, "end get_filter\n", 0, 0, 0 );
383         return( err );
384 }
385
386 static int
387 get_filter_list( BerElement *ber, Filter f )
388 {
389         Filter          new, tail;
390         int             err;
391         unsigned long   tag, len;
392         char            *last;
393
394         Debug( LDAP_DEBUG_TRACE, "get_filter_list\n", 0, 0, 0 );
395
396 #ifdef LDAP_COMPAT30
397         if ( ldap_compat == 30 )
398                 (void) ber_skip_tag( ber, &len );
399 #endif
400         f->FUFILT = tail = NULLFILTER;
401         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
402             tag = ber_next_element( ber, &len, last ) ) {
403                 if ( (err = get_filter( ber, &new )) != 0 )
404                         return( err );
405
406                 if ( f->FUFILT == NULLFILTER ) {
407                         f->FUFILT = new;
408                 } else {
409                         tail->flt_next = new;
410                 }
411                 tail = new;
412         }
413
414         Debug( LDAP_DEBUG_TRACE, "end get_filter_list\n", 0, 0, 0 );
415         return( 0 );
416 }
417
418 static int
419 get_substring_filter( BerElement *ber, Filter f )
420 {
421         unsigned long   tag, len;
422         char            typestr[64];
423         AttributeType   type;
424         char            *valstr, *last;
425         AttributeValue  value;
426
427         Debug( LDAP_DEBUG_TRACE, "get_substring_filter\n", 0, 0, 0 );
428
429 #ifdef LDAP_COMPAT30
430         if ( ldap_compat == 30 )
431                 (void) ber_skip_tag( ber, &len );
432 #endif
433
434         f->flt_type = FILTER_ITEM;
435         f->FUITEM.fi_type = FILTERITEM_SUBSTRINGS;
436         len = sizeof(typestr);
437         if ( ber_scanf( ber, "{s", typestr, &len ) == LBER_ERROR ) {
438                 return( LDAP_PROTOCOL_ERROR );
439         }
440         if ( (type = str2AttrT( typestr )) == NULLAttrT ) {
441                 return( LDAP_UNDEFINED_TYPE );
442         }
443         f->FUITEM.UNSUB.fi_sub_type = type;
444         f->FUITEM.UNSUB.fi_sub_initial = NULLAV;
445         f->FUITEM.UNSUB.fi_sub_any = NULLAV;
446         f->FUITEM.UNSUB.fi_sub_final = NULLAV;
447         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
448             tag = ber_next_element( ber, &len, last ) ) {
449                 AV_Sequence     avs, any_end;
450
451 #ifdef LDAP_COMPAT30
452                 if ( ldap_compat == 30 ) {
453                         if ( ber_scanf( ber, "{a}", &valstr ) == LBER_ERROR ) {
454                                 return( LDAP_PROTOCOL_ERROR );
455                         }
456                 } else
457 #endif
458                         if ( ber_scanf( ber, "a", &valstr ) == LBER_ERROR ) {
459                                 return( LDAP_PROTOCOL_ERROR );
460                         }
461
462                 value = ldap_str2AttrV( valstr, type->oa_syntax );
463                 free( valstr );
464
465                 if ( value == NULLAttrV ) {
466                         return( LDAP_INVALID_SYNTAX );
467                 }
468
469                 if ( (avs = avs_comp_new( value )) == NULLAV )
470                         return( LDAP_OPERATIONS_ERROR );
471
472                 switch ( tag ) {
473 #ifdef LDAP_COMPAT20
474                 case OLD_LDAP_SUBSTRING_INITIAL:
475 #endif
476 #ifdef LDAP_COMPAT30
477                 case LDAP_SUBSTRING_INITIAL_30:
478 #endif
479                 case LDAP_SUBSTRING_INITIAL:
480                         Debug( LDAP_DEBUG_ARGS, "  INITIAL\n", 0, 0, 0 );
481                         if ( f->FUITEM.UNSUB.fi_sub_initial != NULLAV
482                             && f->FUITEM.UNSUB.fi_sub_initial->avseq_next
483                             != NULLAV ) {
484                                 return( LDAP_PROTOCOL_ERROR );
485                         }
486                         f->FUITEM.UNSUB.fi_sub_initial = avs;
487                         break;
488
489 #ifdef LDAP_COMPAT20
490                 case OLD_LDAP_SUBSTRING_ANY:
491 #endif
492 #ifdef LDAP_COMPAT30
493                 case LDAP_SUBSTRING_ANY_30:
494 #endif
495                 case LDAP_SUBSTRING_ANY:
496                         Debug( LDAP_DEBUG_ARGS, "  ANY\n", 0, 0, 0 );
497         
498                         if (f->FUITEM.UNSUB.fi_sub_any != NULLAV) {
499                                 any_end->avseq_next = avs;
500                         } else {
501                                 f->FUITEM.UNSUB.fi_sub_any = avs;
502                         }
503
504                         any_end = avs;
505                         break;
506
507 #ifdef LDAP_COMPAT20
508                 case OLD_LDAP_SUBSTRING_FINAL:
509 #endif
510 #ifdef LDAP_COMPAT30
511                 case LDAP_SUBSTRING_FINAL_30:
512 #endif
513                 case LDAP_SUBSTRING_FINAL:
514                         Debug( LDAP_DEBUG_ARGS, "  FINAL\n", 0, 0, 0 );
515                         if ( f->FUITEM.UNSUB.fi_sub_final != NULLAV
516                             && f->FUITEM.UNSUB.fi_sub_final->avseq_next
517                             != NULLAV ) {
518                                 return( LDAP_PROTOCOL_ERROR );
519                         }
520                         f->FUITEM.UNSUB.fi_sub_final = avs;
521                         break;
522
523                 default:
524                         Debug( LDAP_DEBUG_ARGS, "  unknown type\n", tag, 0, 0 );
525                         return( LDAP_PROTOCOL_ERROR );
526                 }
527         }
528
529         Debug( LDAP_DEBUG_TRACE, "end get_substring_filter\n", 0, 0, 0 );
530         return( 0 );
531 }
532
533 void
534 search_result(
535     Sockbuf                     *sb,
536     struct msg                  *m,
537     struct ds_search_result     *sr
538 )
539 {
540         EntryInfo       *e;
541         BerElement      *ber;
542         int             rc;
543
544         Debug( LDAP_DEBUG_TRACE, "search_result\n", 0, 0, 0 );
545
546         ber = NULL;
547
548         if ( ! sr->srr_correlated ) {
549                 Debug( LDAP_DEBUG_ARGS, "correlating results\n", 0, 0, 0 );
550                 correlate_search_results( sr );
551         }
552
553 #ifdef LDAP_CONNECTIONLESS
554         if ( m->m_cldap ) {
555                 if ((ber = der_alloc()) == NULLBER ) {
556                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
557                             LDAP_OPERATIONS_ERROR, NULL, "der_alloc" );
558                         return;
559                 }
560                 if ( ber_printf( ber, "t{is{", LBER_SEQUENCE, m->m_msgid,
561                     "" ) == -1 ) {
562                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
563                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
564                         return;
565                 }
566         }
567 #endif
568
569         for ( e = sr->CSR_entries; e != NULLENTRYINFO; e = e->ent_next ) {
570                 Debug( LDAP_DEBUG_ARGS, "\tentry:\n", 0, 0, 0 );
571
572 #ifdef LDAP_CONNECTIONLESS
573                 if ( !m->m_cldap )
574 #endif /* LDAP_CONNECTIONLESS */
575
576                         if ( (ber = der_alloc()) == NULLBER ) {
577                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
578                                     LDAP_OPERATIONS_ERROR, NULL, "der_alloc" );
579                                 return;
580                         }
581
582 #ifdef LDAP_COMPAT20
583                 if ( version == 1 ) {
584                         if ( ber_printf( ber, "t{it{", OLD_LBER_SEQUENCE,
585                             m->m_msgid, OLD_LDAP_RES_SEARCH_ENTRY ) == -1 ) {
586                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
587                                     LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
588                                 return;
589                         }
590                 } else
591 #endif
592 #ifdef LDAP_COMPAT30
593                 if ( ldap_compat == 30 ) {
594                         if ( ber_printf( ber, "{it{{", m->m_msgid,
595                             LDAP_RES_SEARCH_ENTRY ) == -1 ) {
596                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
597                                     LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
598                                 return;
599                         }
600                 } else
601 #endif
602 #ifdef LDAP_CONNECTIONLESS
603                 if ( m->m_cldap )
604                         rc = ber_printf( ber, "t{", LDAP_RES_SEARCH_ENTRY );
605                 else
606 #endif /* LDAP_CONNECTIONLESS */
607                         rc = ber_printf( ber, "{it{", m->m_msgid,
608                             LDAP_RES_SEARCH_ENTRY );
609
610                 if ( rc == -1 ) {
611                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
612                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
613                         return;
614                 }
615
616 #ifdef LDAP_CONNECTIONLESS
617                 if (  m->m_cldap )
618                         rc = encode_dn( ber, e->ent_dn, m->m_searchbase );
619 #endif /* LDAP_CONNECTIONLESS */
620                 else
621                         rc = encode_dn( ber, e->ent_dn, NULLDN );
622
623                 if ( rc == -1 ) {
624                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
625                             LDAP_OPERATIONS_ERROR, NULL, "encode_dn" );
626                         return;
627                 }
628
629                 if ( encode_attrs( ber, e->ent_attr ) == -1 ) {
630                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
631                             LDAP_OPERATIONS_ERROR, NULL, "encode_attrs" );
632                         return;
633                 }
634
635 #ifdef LDAP_COMPAT20
636                 if ( version == 1 ) {
637                         if ( ber_printf( ber, "}}" ) == -1 ) {
638                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
639                                     LDAP_OPERATIONS_ERROR, NULL,
640                                     "ber_printf 2" );
641                                 return;
642                         }
643                 } else
644 #endif
645 #ifdef LDAP_COMPAT30
646                 if ( ldap_compat == 30 ) {
647                         if ( ber_printf( ber, "}}}" ) == -1 ) {
648                                 send_ldap_msgresult( sb, SEARCHRESTAG, m,
649                                     LDAP_OPERATIONS_ERROR, NULL,
650                                     "ber_printf 2" );
651                                 return;
652                         }
653                 } else
654 #endif
655 #ifdef LDAP_CONNECTIONLESS
656                 if ( m->m_cldap )
657                         rc = ber_printf( ber, "}" );
658                 else
659 #endif /* LDAP_CONNECTIONLESS */
660                         rc = ber_printf( ber, "}}" );
661
662                 if ( rc == -1 ) {
663                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
664                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf 2" );
665                         return;
666                 }
667
668 #ifdef LDAP_DEBUG
669                 if ( ldap_debug & LDAP_DEBUG_BER )
670                         trace_ber( 0, ber->ber_ptr - ber->ber_buf,
671                             ber->ber_buf, stderr, 0, 0 );
672 #endif
673
674 #ifdef LDAP_CONNECTIONLESS
675                 if ( !m->m_cldap )
676 #endif
677                         (void) ber_flush( sb, ber, 1 );
678         }
679
680         switch ( sr->CSR_limitproblem ) {
681         case LSR_NOLIMITPROBLEM:
682                 rc = LDAP_SUCCESS;
683                 break;
684         case LSR_TIMELIMITEXCEEDED:
685                 rc = LDAP_TIMELIMIT_EXCEEDED;
686                 break;
687         case LSR_SIZELIMITEXCEEDED:
688         case LSR_ADMINSIZEEXCEEDED:
689                 rc = LDAP_SIZELIMIT_EXCEEDED;
690                 break;
691         }
692
693         Debug( LDAP_DEBUG_ARGS, "\tresult:\n", 0, 0, 0 );
694
695 #ifdef LDAP_CONNECTIONLESS
696         if ( m->m_cldap ) {
697                 if ( ber_printf( ber, "t{ess}}}", SEARCHRESTAG, rc, "", "" )
698                     == -1 ) {
699                         send_ldap_msgresult( sb, SEARCHRESTAG, m,
700                             LDAP_OPERATIONS_ERROR, NULL, "ber_printf" );
701                         return;
702                 }
703                 SAFEMEMCPY( (char *)sb->sb_useaddr, &m->m_clientaddr,
704                     sizeof( struct sockaddr ));
705                 if ( ber_flush( sb, ber, 1 ) != 0 ) {
706                     send_ldap_msgresult( sb, SEARCHRESTAG, m, 
707                         LDAP_RESULTS_TOO_LARGE, NULL, "ber_flush" );
708                 }
709         } else
710 #endif
711         send_ldap_msgresult( sb, SEARCHRESTAG, m, rc, NULL, "" );
712
713         return;
714 }