Back to index

openldap  2.4.31
io.c
Go to the documentation of this file.
00001 /* io.c - ber general i/o routines */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* Portions Copyright (c) 1990 Regents of the University of Michigan.
00017  * All rights reserved.
00018  *
00019  * Redistribution and use in source and binary forms are permitted
00020  * provided that this notice is preserved and that due credit is given
00021  * to the University of Michigan at Ann Arbor. The name of the University
00022  * may not be used to endorse or promote products derived from this
00023  * software without specific prior written permission. This software
00024  * is provided ``as is'' without express or implied warranty.
00025  */
00026 /* ACKNOWLEDGEMENTS:
00027  * This work was originally developed by the University of Michigan
00028  * (as part of U-MICH LDAP).
00029  */
00030 
00031 #include "portable.h"
00032 
00033 #include <stdio.h>
00034 
00035 #include <ac/stdlib.h>
00036 
00037 #include <ac/ctype.h>
00038 #include <ac/errno.h>
00039 #include <ac/socket.h>
00040 #include <ac/string.h>
00041 #include <ac/unistd.h>
00042 
00043 #ifdef HAVE_IO_H
00044 #include <io.h>
00045 #endif
00046 
00047 #include "lber-int.h"
00048 #include "ldap_log.h"
00049 
00050 ber_slen_t
00051 ber_skip_data(
00052        BerElement *ber,
00053        ber_len_t len )
00054 {
00055        ber_len_t     actuallen, nleft;
00056 
00057        assert( ber != NULL );
00058        assert( LBER_VALID( ber ) );
00059 
00060        nleft = ber_pvt_ber_remaining( ber );
00061        actuallen = nleft < len ? nleft : len;
00062        ber->ber_ptr += actuallen;
00063        ber->ber_tag = *(unsigned char *)ber->ber_ptr;
00064 
00065        return( (ber_slen_t) actuallen );
00066 }
00067 
00068 /*
00069  * Read from the ber buffer.  The caller must maintain ber->ber_tag.
00070  * Do not use to read whole tags.  See ber_get_tag() and ber_skip_data().
00071  */
00072 ber_slen_t
00073 ber_read(
00074        BerElement *ber,
00075        char *buf,
00076        ber_len_t len )
00077 {
00078        ber_len_t     actuallen, nleft;
00079 
00080        assert( ber != NULL );
00081        assert( buf != NULL );
00082        assert( LBER_VALID( ber ) );
00083 
00084        nleft = ber_pvt_ber_remaining( ber );
00085        actuallen = nleft < len ? nleft : len;
00086 
00087        AC_MEMCPY( buf, ber->ber_ptr, actuallen );
00088 
00089        ber->ber_ptr += actuallen;
00090 
00091        return( (ber_slen_t) actuallen );
00092 }
00093 
00094 /*
00095  * Write to the ber buffer.
00096  * Note that ber_start_seqorset/ber_put_seqorset() bypass ber_write().
00097  */
00098 ber_slen_t
00099 ber_write(
00100        BerElement *ber,
00101        LDAP_CONST char *buf,
00102        ber_len_t len,
00103        int zero )    /* nonzero is unsupported from OpenLDAP 2.4.18 */
00104 {
00105        char **p;
00106 
00107        assert( ber != NULL );
00108        assert( buf != NULL );
00109        assert( LBER_VALID( ber ) );
00110 
00111        if ( zero != 0 ) {
00112               ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug, "%s",
00113                      "ber_write: nonzero 4th argument not supported\n" );
00114               return( -1 );
00115        }
00116 
00117        p = ber->ber_sos_ptr == NULL ? &ber->ber_ptr : &ber->ber_sos_ptr;
00118        if ( len > (ber_len_t) (ber->ber_end - *p) ) {
00119               if ( ber_realloc( ber, len ) != 0 ) return( -1 );
00120        }
00121        AC_MEMCPY( *p, buf, len );
00122        *p += len;
00123 
00124        return( (ber_slen_t) len );
00125 }
00126 
00127 /* Resize the ber buffer */
00128 int
00129 ber_realloc( BerElement *ber, ber_len_t len )
00130 {
00131        ber_len_t     total, offset, sos_offset;
00132        char          *buf;
00133 
00134        assert( ber != NULL );
00135        assert( LBER_VALID( ber ) );
00136 
00137        /* leave room for ber_flatten() to \0-terminate ber_buf */
00138        if ( ++len == 0 ) {
00139               return( -1 );
00140        }
00141 
00142        total = ber_pvt_ber_total( ber );
00143 
00144 #define LBER_EXBUFSIZ       4060 /* a few words less than 2^N for binary buddy */
00145 #if defined( LBER_EXBUFSIZ ) && LBER_EXBUFSIZ > 0
00146 # ifndef notdef
00147        /* don't realloc by small amounts */
00148        total += len < LBER_EXBUFSIZ ? LBER_EXBUFSIZ : len;
00149 # else
00150        {      /* not sure what value this adds.  reduce fragmentation? */
00151               ber_len_t have = (total + (LBER_EXBUFSIZE - 1)) / LBER_EXBUFSIZ;
00152               ber_len_t need = (len + (LBER_EXBUFSIZ - 1)) / LBER_EXBUFSIZ;
00153               total = ( have + need ) * LBER_EXBUFSIZ;
00154        }
00155 # endif
00156 #else
00157        total += len; /* realloc just what's needed */
00158 #endif
00159 
00160        if ( total < len || total > (ber_len_t)-1 / 2 /* max ber_slen_t */ ) {
00161               return( -1 );
00162        }
00163 
00164        buf = ber->ber_buf;
00165        offset = ber->ber_ptr - buf;
00166        sos_offset = ber->ber_sos_ptr ? ber->ber_sos_ptr - buf : 0;
00167        /* if ber_sos_ptr != NULL, it is > ber_buf so that sos_offset > 0 */
00168 
00169        buf = (char *) ber_memrealloc_x( buf, total, ber->ber_memctx );
00170        if ( buf == NULL ) {
00171               return( -1 );
00172        }
00173 
00174        ber->ber_buf = buf;
00175        ber->ber_end = buf + total;
00176        ber->ber_ptr = buf + offset;
00177        if ( sos_offset )
00178               ber->ber_sos_ptr = buf + sos_offset;
00179 
00180        return( 0 );
00181 }
00182 
00183 void
00184 ber_free_buf( BerElement *ber )
00185 {
00186        assert( LBER_VALID( ber ) );
00187 
00188        if ( ber->ber_buf) ber_memfree_x( ber->ber_buf, ber->ber_memctx );
00189 
00190        ber->ber_buf = NULL;
00191        ber->ber_sos_ptr = NULL;
00192        ber->ber_valid = LBER_UNINITIALIZED;
00193 }
00194 
00195 void
00196 ber_free( BerElement *ber, int freebuf )
00197 {
00198        if( ber == NULL ) {
00199               LDAP_MEMORY_DEBUG_ASSERT( ber != NULL );
00200               return;
00201        }
00202 
00203        if( freebuf ) ber_free_buf( ber );
00204 
00205        ber_memfree_x( (char *) ber, ber->ber_memctx );
00206 }
00207 
00208 int
00209 ber_flush( Sockbuf *sb, BerElement *ber, int freeit )
00210 {
00211        return ber_flush2( sb, ber,
00212               freeit ? LBER_FLUSH_FREE_ON_SUCCESS
00213                      : LBER_FLUSH_FREE_NEVER );
00214 }
00215 
00216 int
00217 ber_flush2( Sockbuf *sb, BerElement *ber, int freeit )
00218 {
00219        ber_len_t     towrite;
00220        ber_slen_t    rc;
00221 
00222        assert( sb != NULL );
00223        assert( ber != NULL );
00224        assert( SOCKBUF_VALID( sb ) );
00225        assert( LBER_VALID( ber ) );
00226 
00227        if ( ber->ber_rwptr == NULL ) {
00228               ber->ber_rwptr = ber->ber_buf;
00229        }
00230        towrite = ber->ber_ptr - ber->ber_rwptr;
00231 
00232        if ( sb->sb_debug ) {
00233               ber_log_printf( LDAP_DEBUG_TRACE, sb->sb_debug,
00234                      "ber_flush2: %ld bytes to sd %ld%s\n",
00235                      towrite, (long) sb->sb_fd,
00236                      ber->ber_rwptr != ber->ber_buf ?  " (re-flush)" : "" );
00237               ber_log_bprint( LDAP_DEBUG_BER, sb->sb_debug,
00238                      ber->ber_rwptr, towrite );
00239        }
00240 
00241        while ( towrite > 0 ) {
00242 #ifdef LBER_TRICKLE
00243               sleep(1);
00244               rc = ber_int_sb_write( sb, ber->ber_rwptr, 1 );
00245 #else
00246               rc = ber_int_sb_write( sb, ber->ber_rwptr, towrite );
00247 #endif
00248               if ( rc <= 0 ) {
00249                      if ( freeit & LBER_FLUSH_FREE_ON_ERROR ) ber_free( ber, 1 );
00250                      return -1;
00251               }
00252               towrite -= rc;
00253               ber->ber_rwptr += rc;
00254        } 
00255 
00256        if ( freeit & LBER_FLUSH_FREE_ON_SUCCESS ) ber_free( ber, 1 );
00257 
00258        return 0;
00259 }
00260 
00261 BerElement *
00262 ber_alloc_t( int options )
00263 {
00264        BerElement    *ber;
00265 
00266        ber = (BerElement *) LBER_CALLOC( 1, sizeof(BerElement) );
00267 
00268        if ( ber == NULL ) {
00269               return NULL;
00270        }
00271 
00272        ber->ber_valid = LBER_VALID_BERELEMENT;
00273        ber->ber_tag = LBER_DEFAULT;
00274        ber->ber_options = options;
00275        ber->ber_debug = ber_int_debug;
00276 
00277        assert( LBER_VALID( ber ) );
00278        return ber;
00279 }
00280 
00281 BerElement *
00282 ber_alloc( void )    /* deprecated */
00283 {
00284        return ber_alloc_t( 0 );
00285 }
00286 
00287 BerElement *
00288 der_alloc( void )    /* deprecated */
00289 {
00290        return ber_alloc_t( LBER_USE_DER );
00291 }
00292 
00293 BerElement *
00294 ber_dup( BerElement *ber )
00295 {
00296        BerElement    *new;
00297 
00298        assert( ber != NULL );
00299        assert( LBER_VALID( ber ) );
00300 
00301        if ( (new = ber_alloc_t( ber->ber_options )) == NULL ) {
00302               return NULL;
00303        }
00304 
00305        *new = *ber;
00306 
00307        assert( LBER_VALID( new ) );
00308        return( new );
00309 }
00310 
00311 
00312 void
00313 ber_init2( BerElement *ber, struct berval *bv, int options )
00314 {
00315        assert( ber != NULL );
00316 
00317        (void) memset( (char *)ber, '\0', sizeof( BerElement ));
00318        ber->ber_valid = LBER_VALID_BERELEMENT;
00319        ber->ber_tag = LBER_DEFAULT;
00320        ber->ber_options = (char) options;
00321        ber->ber_debug = ber_int_debug;
00322 
00323        if ( bv != NULL ) {
00324               ber->ber_buf = bv->bv_val;
00325               ber->ber_ptr = ber->ber_buf;
00326               ber->ber_end = ber->ber_buf + bv->bv_len;
00327        }
00328 
00329        assert( LBER_VALID( ber ) );
00330 }
00331 
00332 /* OLD U-Mich ber_init() */
00333 void
00334 ber_init_w_nullc( BerElement *ber, int options )
00335 {
00336        ber_init2( ber, NULL, options );
00337 }
00338 
00339 /* New C-API ber_init() */
00340 /* This function constructs a BerElement containing a copy
00341 ** of the data in the bv argument.
00342 */
00343 BerElement *
00344 ber_init( struct berval *bv )
00345 {
00346        BerElement *ber;
00347 
00348        assert( bv != NULL );
00349 
00350        if ( bv == NULL ) {
00351               return NULL;
00352        }
00353 
00354        ber = ber_alloc_t( 0 );
00355 
00356        if( ber == NULL ) {
00357               /* allocation failed */
00358               return NULL;
00359        }
00360 
00361        /* copy the data */
00362        if ( ((ber_len_t) ber_write ( ber, bv->bv_val, bv->bv_len, 0 ))
00363               != bv->bv_len )
00364        {
00365               /* write failed, so free and return NULL */
00366               ber_free( ber, 1 );
00367               return NULL;
00368        }
00369 
00370        ber_reset( ber, 1 ); /* reset the pointer to the start of the buffer */
00371        return ber;
00372 }
00373 
00374 /* New C-API ber_flatten routine */
00375 /* This routine allocates a struct berval whose contents are a BER
00376 ** encoding taken from the ber argument.  The bvPtr pointer points to
00377 ** the returned berval.
00378 **
00379 ** ber_flatten2 is the same, but uses a struct berval passed by
00380 ** the caller. If alloc is 0 the returned bv uses the ber buf directly.
00381 */
00382 int ber_flatten2(
00383        BerElement *ber,
00384        struct berval *bv,
00385        int alloc )
00386 {
00387        assert( bv != NULL );
00388 
00389        if ( bv == NULL ) {
00390               return -1;
00391        }
00392 
00393        if ( ber == NULL ) {
00394               /* ber is null, create an empty berval */
00395               bv->bv_val = NULL;
00396               bv->bv_len = 0;
00397 
00398        } else if ( ber->ber_sos_ptr != NULL ) {
00399               /* unmatched "{" and "}" */
00400               return -1;
00401 
00402        } else {
00403               /* copy the berval */
00404               ber_len_t len = ber_pvt_ber_write( ber );
00405 
00406               if ( alloc ) {
00407                      bv->bv_val = (char *) ber_memalloc_x( len + 1, ber->ber_memctx );
00408                      if ( bv->bv_val == NULL ) {
00409                             return -1;
00410                      }
00411                      AC_MEMCPY( bv->bv_val, ber->ber_buf, len );
00412                      bv->bv_val[len] = '\0';
00413               } else if ( ber->ber_buf != NULL ) {
00414                      bv->bv_val = ber->ber_buf;
00415                      bv->bv_val[len] = '\0';
00416               } else {
00417                      bv->bv_val = "";
00418               }
00419               bv->bv_len = len;
00420        }
00421        return 0;
00422 }
00423 
00424 int ber_flatten(
00425        BerElement *ber,
00426        struct berval **bvPtr)
00427 {
00428        struct berval *bv;
00429        int rc;
00430  
00431        assert( bvPtr != NULL );
00432 
00433        if(bvPtr == NULL) {
00434               return -1;
00435        }
00436 
00437        bv = ber_memalloc_x( sizeof(struct berval), ber->ber_memctx );
00438        if ( bv == NULL ) {
00439               return -1;
00440        }
00441        rc = ber_flatten2(ber, bv, 1);
00442        if (rc == -1) {
00443               ber_memfree_x(bv, ber->ber_memctx);
00444        } else {
00445               *bvPtr = bv;
00446        }
00447        return rc;
00448 }
00449 
00450 void
00451 ber_reset( BerElement *ber, int was_writing )
00452 {
00453        assert( ber != NULL );
00454        assert( LBER_VALID( ber ) );
00455 
00456        if ( was_writing ) {
00457               ber->ber_end = ber->ber_ptr;
00458               ber->ber_ptr = ber->ber_buf;
00459 
00460        } else {
00461               ber->ber_ptr = ber->ber_end;
00462        }
00463 
00464        ber->ber_rwptr = NULL;
00465 }
00466 
00467 /*
00468  * A rewrite of ber_get_next that can safely be called multiple times 
00469  * for the same packet. It will simply continue where it stopped until
00470  * a full packet is read.
00471  */
00472 
00473 #define LENSIZE      4
00474 
00475 ber_tag_t
00476 ber_get_next(
00477        Sockbuf *sb,
00478        ber_len_t *len,
00479        BerElement *ber )
00480 {
00481        assert( sb != NULL );
00482        assert( len != NULL );
00483        assert( ber != NULL );
00484        assert( SOCKBUF_VALID( sb ) );
00485        assert( LBER_VALID( ber ) );
00486 
00487        if ( ber->ber_debug & LDAP_DEBUG_TRACE ) {
00488               ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
00489                      "ber_get_next\n" );
00490        }
00491 
00492        /*
00493         * Any ber element looks like this: tag length contents.
00494         * Assuming everything's ok, we return the tag byte (we
00495         * can assume a single byte), return the length in len,
00496         * and the rest of the undecoded element in buf.
00497         *
00498         * Assumptions:
00499         *     1) small tags (less than 128)
00500         *     2) definite lengths
00501         *     3) primitive encodings used whenever possible
00502         *
00503         * The code also handles multi-byte tags. The first few bytes
00504         * of the message are read to check for multi-byte tags and
00505         * lengths. These bytes are temporarily stored in the ber_tag,
00506         * ber_len, and ber_usertag fields of the berelement until
00507         * tag/len parsing is complete. After this parsing, any leftover
00508         * bytes and the rest of the message are copied into the ber_buf.
00509         *
00510         * We expect tag and len to be at most 32 bits wide.
00511         */
00512 
00513        if (ber->ber_rwptr == NULL) {
00514               assert( ber->ber_buf == NULL );
00515               ber->ber_rwptr = (char *) &ber->ber_len-1;
00516               ber->ber_ptr = ber->ber_rwptr;
00517               ber->ber_tag = 0;
00518        }
00519 
00520        while (ber->ber_rwptr > (char *)&ber->ber_tag && ber->ber_rwptr <
00521               (char *)&ber->ber_len + LENSIZE*2) {
00522               ber_slen_t sblen;
00523               char buf[sizeof(ber->ber_len)-1];
00524               ber_len_t tlen = 0;
00525 
00526               /* The tag & len can be at most 9 bytes; we try to read up to 8 here */
00527               sock_errset(0);
00528               sblen=((char *)&ber->ber_len + LENSIZE*2 - 1)-ber->ber_rwptr;
00529               /* Trying to read the last len byte of a 9 byte tag+len */
00530               if (sblen<1)
00531                      sblen = 1;
00532               sblen=ber_int_sb_read( sb, ber->ber_rwptr, sblen );
00533               if (sblen<=0) return LBER_DEFAULT;
00534               ber->ber_rwptr += sblen;
00535 
00536               /* We got at least one byte, try to parse the tag. */
00537               if (ber->ber_ptr == (char *)&ber->ber_len-1) {
00538                      ber_tag_t tag;
00539                      unsigned char *p = (unsigned char *)ber->ber_ptr;
00540                      tag = *p++;
00541                      if ((tag & LBER_BIG_TAG_MASK) == LBER_BIG_TAG_MASK) {
00542                             ber_len_t i;
00543                             for (i=1; (char *)p<ber->ber_rwptr; i++) {
00544                                    tag <<= 8;
00545                                    tag |= *p++;
00546                                    if (!(tag & LBER_MORE_TAG_MASK))
00547                                           break;
00548                                    /* Is the tag too big? */
00549                                    if (i == sizeof(ber_tag_t)-1) {
00550                                           sock_errset(ERANGE);
00551                                           return LBER_DEFAULT;
00552                                    }
00553                             }
00554                             /* Did we run out of bytes? */
00555                             if ((char *)p == ber->ber_rwptr) {
00556                                    sock_errset(EWOULDBLOCK);
00557                                    return LBER_DEFAULT;
00558                             }
00559                      }
00560                      ber->ber_tag = tag;
00561                      ber->ber_ptr = (char *)p;
00562               }
00563 
00564               if ( ber->ber_ptr == ber->ber_rwptr ) {
00565                      sock_errset(EWOULDBLOCK);
00566                      return LBER_DEFAULT;
00567               }
00568 
00569               /* Now look for the length */
00570               if (*ber->ber_ptr & 0x80) { /* multi-byte */
00571                      int i;
00572                      unsigned char *p = (unsigned char *)ber->ber_ptr;
00573                      int llen = *p++ & 0x7f;
00574                      if (llen > LENSIZE) {
00575                             sock_errset(ERANGE);
00576                             return LBER_DEFAULT;
00577                      }
00578                      /* Not enough bytes? */
00579                      if (ber->ber_rwptr - (char *)p < llen) {
00580                             sock_errset(EWOULDBLOCK);
00581                             return LBER_DEFAULT;
00582                      }
00583                      for (i=0; i<llen; i++) {
00584                             tlen <<=8;
00585                             tlen |= *p++;
00586                      }
00587                      ber->ber_ptr = (char *)p;
00588               } else {
00589                      tlen = *(unsigned char *)ber->ber_ptr++;
00590               }
00591 
00592               /* Are there leftover data bytes inside ber->ber_len? */
00593               if (ber->ber_ptr < (char *)&ber->ber_usertag) {
00594                      if (ber->ber_rwptr < (char *)&ber->ber_usertag) {
00595                             sblen = ber->ber_rwptr - ber->ber_ptr;
00596                      } else {
00597                             sblen = (char *)&ber->ber_usertag - ber->ber_ptr;
00598                      }
00599                      AC_MEMCPY(buf, ber->ber_ptr, sblen);
00600                      ber->ber_ptr += sblen;
00601               } else {
00602                      sblen = 0;
00603               }
00604               ber->ber_len = tlen;
00605 
00606               /* now fill the buffer. */
00607 
00608               /* make sure length is reasonable */
00609               if ( ber->ber_len == 0 ) {
00610                      sock_errset(ERANGE);
00611                      return LBER_DEFAULT;
00612               }
00613 
00614               if ( sb->sb_max_incoming && ber->ber_len > sb->sb_max_incoming ) {
00615                      ber_log_printf( LDAP_DEBUG_CONNS, ber->ber_debug,
00616                             "ber_get_next: sockbuf_max_incoming exceeded "
00617                             "(%ld > %ld)\n", ber->ber_len, sb->sb_max_incoming );
00618                      sock_errset(ERANGE);
00619                      return LBER_DEFAULT;
00620               }
00621 
00622               if (ber->ber_buf==NULL) {
00623                      ber_len_t l = ber->ber_rwptr - ber->ber_ptr;
00624                      /* ber->ber_ptr is always <= ber->ber->ber_rwptr.
00625                       * make sure ber->ber_len agrees with what we've
00626                       * already read.
00627                       */
00628                      if ( ber->ber_len < sblen + l ) {
00629                             sock_errset(ERANGE);
00630                             return LBER_DEFAULT;
00631                      }
00632                      ber->ber_buf = (char *) ber_memalloc_x( ber->ber_len + 1, ber->ber_memctx );
00633                      if (ber->ber_buf==NULL) {
00634                             return LBER_DEFAULT;
00635                      }
00636                      ber->ber_end = ber->ber_buf + ber->ber_len;
00637                      if (sblen) {
00638                             AC_MEMCPY(ber->ber_buf, buf, sblen);
00639                      }
00640                      if (l > 0) {
00641                             AC_MEMCPY(ber->ber_buf + sblen, ber->ber_ptr, l);
00642                             sblen += l;
00643                      }
00644                      *ber->ber_end = '\0';
00645                      ber->ber_ptr = ber->ber_buf;
00646                      ber->ber_usertag = 0;
00647                      if ((ber_len_t)sblen == ber->ber_len) {
00648                             goto done;
00649                      }
00650                      ber->ber_rwptr = ber->ber_buf + sblen;
00651               }
00652        }
00653 
00654        if ((ber->ber_rwptr>=ber->ber_buf) && (ber->ber_rwptr<ber->ber_end)) {
00655               ber_slen_t res;
00656               ber_slen_t to_go;
00657               
00658               to_go = ber->ber_end - ber->ber_rwptr;
00659               assert( to_go > 0 );
00660               
00661               sock_errset(0);
00662               res = ber_int_sb_read( sb, ber->ber_rwptr, to_go );
00663               if (res<=0) return LBER_DEFAULT;
00664               ber->ber_rwptr+=res;
00665               
00666               if (res<to_go) {
00667                      sock_errset(EWOULDBLOCK);
00668                      return LBER_DEFAULT;
00669               }
00670 done:
00671               ber->ber_rwptr = NULL;
00672               *len = ber->ber_len;
00673               if ( ber->ber_debug ) {
00674                      ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
00675                             "ber_get_next: tag 0x%lx len %ld contents:\n",
00676                             ber->ber_tag, ber->ber_len );
00677                      ber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 );
00678               }
00679               return (ber->ber_tag);
00680        }
00681 
00682        assert( 0 ); /* ber structure is messed up ?*/
00683        return LBER_DEFAULT;
00684 }
00685 
00686 char *
00687 ber_start( BerElement* ber )
00688 {
00689        return ber->ber_buf;
00690 }
00691 
00692 int
00693 ber_len( BerElement* ber )
00694 {
00695        return ( ber->ber_end - ber->ber_buf );
00696 }
00697 
00698 int
00699 ber_ptrlen( BerElement* ber )
00700 {
00701        return ( ber->ber_ptr - ber->ber_buf );
00702 }
00703 
00704 void
00705 ber_rewind ( BerElement * ber )
00706 {
00707        ber->ber_rwptr = NULL;
00708        ber->ber_sos_ptr = NULL;
00709        ber->ber_end = ber->ber_ptr;
00710        ber->ber_ptr = ber->ber_buf;
00711 #if 0  /* TODO: Should we add this? */
00712        ber->ber_tag = LBER_DEFAULT;
00713        ber->ber_usertag = 0;
00714 #endif
00715 }
00716 
00717 int
00718 ber_remaining( BerElement * ber )
00719 {
00720        return ber_pvt_ber_remaining( ber );
00721 }