コード例 #1
0
ファイル: encode.c プロジェクト: szakats/bzflag_mirror
int
ber_put_ostring(
	BerElement *ber,
	LDAP_CONST char *str,
	ber_len_t len,
	ber_tag_t tag )
{
	int taglen, lenlen, rc;

	assert( ber != NULL );
	assert( str != NULL );

	assert( LBER_VALID( ber ) );

	if ( tag == LBER_DEFAULT ) {
		tag = LBER_OCTETSTRING;
	}

	if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 )
		return -1;

	if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 ||
		(ber_len_t) ber_write( ber, str, len, 0 ) != len )
	{
		rc = -1;
	} else {
		/* return length of tag + length + contents */
		rc = taglen + lenlen + len;
	}

	return rc;
}
コード例 #2
0
ファイル: encode.c プロジェクト: szakats/bzflag_mirror
int
ber_put_boolean(
	BerElement *ber,
	ber_int_t boolval,
	ber_tag_t tag )
{
	int				taglen;
	unsigned char	c;

	assert( ber != NULL );
	assert( LBER_VALID( ber ) );

	if ( tag == LBER_DEFAULT )
		tag = LBER_BOOLEAN;

	if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) {
		return -1;
	}

	if ( ber_put_len( ber, 1, 0 ) != 1 ) {
		return -1;
	}

	c = boolval ? (unsigned char) ~0U : (unsigned char) 0U;

	if ( ber_write( ber, (char *) &c, 1, 0 ) != 1 ) {
		return -1;
	}

	return taglen + 2;
}
コード例 #3
0
ファイル: bprint.c プロジェクト: openldap/openldap
void
ber_dump(
	BerElement *ber,
	int inout )
{
	char buf[132];
	ber_len_t len;

	assert( ber != NULL );
	assert( LBER_VALID( ber ) );

	if ( inout == 1 ) {
		len = ber_pvt_ber_remaining(ber);
	} else {
		len = ber_pvt_ber_write(ber);
	}

	sprintf( buf, "ber_dump: buf=%p ptr=%p end=%p len=%ld\n",
		ber->ber_buf,
		ber->ber_ptr,
		ber->ber_end,
		(long) len );

	(void) (*ber_pvt_log_print)( buf );

	ber_bprint( ber->ber_ptr, len );
}
コード例 #4
0
ファイル: io.c プロジェクト: FarazShaikh/LikewiseSMB2
ber_slen_t
ber_write(
	BerElement *ber,
	LDAP_CONST char *buf,
	ber_len_t len,
	int nosos )
{
	assert( ber != NULL );
	assert( buf != NULL );

	assert( LBER_VALID( ber ) );

	if ( nosos || ber->ber_sos == NULL ) {
		if ( ber->ber_ptr + len > ber->ber_end ) {
			if ( ber_realloc( ber, len ) != 0 ) return( -1 );
		}
		AC_MEMCPY( ber->ber_ptr, buf, (size_t)len );
		ber->ber_ptr += len;
		return( (ber_slen_t) len );

	} else {
		if ( ber->ber_sos->sos_ptr + len > ber->ber_end ) {
			if ( ber_realloc( ber, len ) != 0 ) return( -1 );
		}
		AC_MEMCPY( ber->ber_sos->sos_ptr, buf, (size_t)len );
		ber->ber_sos->sos_ptr += len;
		ber->ber_sos->sos_clen += len;
		return( (ber_slen_t) len );
	}
}
コード例 #5
0
ファイル: io.c プロジェクト: bagel/openldap-ga
/*
 * Write to the ber buffer.
 * Note that ber_start_seqorset/ber_put_seqorset() bypass ber_write().
 */
ber_slen_t
ber_write(
	BerElement *ber,
	LDAP_CONST char *buf,
	ber_len_t len,
	int zero )	/* nonzero is unsupported from OpenLDAP 2.4.18 */
{
	char **p;

	assert( ber != NULL );
	assert( buf != NULL );
	assert( LBER_VALID( ber ) );

	if ( zero != 0 ) {
		ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug, "%s",
			"ber_write: nonzero 4th argument not supported\n" );
		return( -1 );
	}

	p = ber->ber_sos_ptr == NULL ? &ber->ber_ptr : &ber->ber_sos_ptr;
	if ( len > (ber_len_t) (ber->ber_end - *p) ) {
		if ( ber_realloc( ber, len ) != 0 ) return( -1 );
	}
	AC_MEMCPY( *p, buf, len );
	*p += len;

	return( (ber_slen_t) len );
}
コード例 #6
0
ファイル: encode.c プロジェクト: szakats/bzflag_mirror
static int
ber_put_tag(
	BerElement	*ber,
	ber_tag_t tag,
	int nosos )
{
	int rc;
	int taglen;
	int	i;
	unsigned char nettag[sizeof(ber_tag_t)];

	assert( ber != NULL );
	assert( LBER_VALID( ber ) );

	taglen = ber_calc_taglen( tag );

	for( i=taglen-1; i>=0; i-- ) {
		nettag[i] = (unsigned char)(tag & 0xffU);
		tag >>= 8;
	}

	rc = ber_write( ber, (char *) nettag, taglen, nosos );

	return rc;
}
コード例 #7
0
ファイル: io.c プロジェクト: bagel/openldap-ga
void
ber_free_buf( BerElement *ber )
{
	assert( LBER_VALID( ber ) );

	if ( ber->ber_buf) ber_memfree_x( ber->ber_buf, ber->ber_memctx );

	ber->ber_buf = NULL;
	ber->ber_sos_ptr = NULL;
	ber->ber_valid = LBER_UNINITIALIZED;
}
コード例 #8
0
ファイル: io.c プロジェクト: bagel/openldap-ga
/* Resize the ber buffer */
int
ber_realloc( BerElement *ber, ber_len_t len )
{
	ber_len_t	total, offset, sos_offset;
	char		*buf;

	assert( ber != NULL );
	assert( LBER_VALID( ber ) );

	/* leave room for ber_flatten() to \0-terminate ber_buf */
	if ( ++len == 0 ) {
		return( -1 );
	}

	total = ber_pvt_ber_total( ber );

#define LBER_EXBUFSIZ	4060 /* a few words less than 2^N for binary buddy */
#if defined( LBER_EXBUFSIZ ) && LBER_EXBUFSIZ > 0
# ifndef notdef
	/* don't realloc by small amounts */
	total += len < LBER_EXBUFSIZ ? LBER_EXBUFSIZ : len;
# else
	{	/* not sure what value this adds.  reduce fragmentation? */
		ber_len_t have = (total + (LBER_EXBUFSIZE - 1)) / LBER_EXBUFSIZ;
		ber_len_t need = (len + (LBER_EXBUFSIZ - 1)) / LBER_EXBUFSIZ;
		total = ( have + need ) * LBER_EXBUFSIZ;
	}
# endif
#else
	total += len;	/* realloc just what's needed */
#endif

	if ( total < len || total > (ber_len_t)-1 / 2 /* max ber_slen_t */ ) {
		return( -1 );
	}

	buf = ber->ber_buf;
	offset = ber->ber_ptr - buf;
	sos_offset = ber->ber_sos_ptr ? ber->ber_sos_ptr - buf : 0;
	/* if ber_sos_ptr != NULL, it is > ber_buf so that sos_offset > 0 */

	buf = (char *) ber_memrealloc_x( buf, total, ber->ber_memctx );
	if ( buf == NULL ) {
		return( -1 );
	}

	ber->ber_buf = buf;
	ber->ber_end = buf + total;
	ber->ber_ptr = buf + offset;
	if ( sos_offset )
		ber->ber_sos_ptr = buf + sos_offset;

	return( 0 );
}
コード例 #9
0
ファイル: encode.c プロジェクト: szakats/bzflag_mirror
static int
ber_put_len( BerElement *ber, ber_len_t len, int nosos )
{
	int rc;
	int		i,j;
	char		lenlen;
	ber_len_t	mask;
	unsigned char netlen[sizeof(ber_len_t)];

	assert( ber != NULL );
	assert( LBER_VALID( ber ) );

	/*
	 * short len if it's less than 128 - one byte giving the len,
	 * with bit 8 0.
	 */

	if ( len <= 127 ) {
		char length_byte = (char) len;
		return ber_write( ber, &length_byte, 1, nosos );
	}

	/*
	 * long len otherwise - one byte with bit 8 set, giving the
	 * length of the length, followed by the length itself.
	 */

	/* find the first non-all-zero byte */
	i = BER_TOP_BYTE(ber_len_t);
	mask = BER_TOP_MASK(ber_len_t);
	for ( ; i > 0; i-- ) {
		/* not all zero */
		if ( len & mask ) break;
		mask >>= 8;
	}
	lenlen = (unsigned char) ++i;
	if ( lenlen > 4 ) return -1;

	lenlen |= 0x80UL;

	/* write the length of the length */
	if ( ber_write( ber, &lenlen, 1, nosos ) != 1 ) return -1;

	for( j=i-1; j>=0; j-- ) {
		netlen[j] = (unsigned char)(len & 0xffU);
		len >>= 8;
	}

	/* write the length itself */
	rc = ber_write( ber, (char *) netlen, i, nosos );

	return rc == i ?  i+1 : -1;
}
コード例 #10
0
ファイル: encode.c プロジェクト: szakats/bzflag_mirror
int
ber_put_string(
	BerElement *ber,
	LDAP_CONST char *str,
	ber_tag_t tag )
{
	assert( ber != NULL );
	assert( str != NULL );

	assert( LBER_VALID( ber ) );

	return ber_put_ostring( ber, str, strlen( str ), tag );
}
コード例 #11
0
ファイル: encode.c プロジェクト: szakats/bzflag_mirror
int
ber_put_int(
	BerElement *ber,
	ber_int_t num,
	ber_tag_t tag )
{
	assert( ber != NULL );
	assert( LBER_VALID( ber ) );

	if ( tag == LBER_DEFAULT ) {
		tag = LBER_INTEGER;
	}

	return ber_put_int_or_enum( ber, num, tag );
}
コード例 #12
0
ファイル: encode.c プロジェクト: szakats/bzflag_mirror
int
ber_put_berval(
	BerElement *ber,
	struct berval *bv,
	ber_tag_t tag )
{
	assert( ber != NULL );
	assert( LBER_VALID( ber ) );

	if( bv == NULL || bv->bv_len == 0 ) {
		return ber_put_ostring( ber, "", (ber_len_t) 0, tag );
	}

	return ber_put_ostring( ber, bv->bv_val, bv->bv_len, tag );
}
コード例 #13
0
ファイル: bprint.c プロジェクト: openldap/openldap
int
ber_log_dump(
	int errlvl,
	int loglvl,
	BerElement *ber,
	int inout )
{
	assert( ber != NULL );
	assert( LBER_VALID( ber ) );

	if ( !ber_log_check( errlvl, loglvl )) {
		return 0;
	}

	ber_dump(ber, inout);
	return 1;
}
コード例 #14
0
ファイル: io.c プロジェクト: bagel/openldap-ga
ber_slen_t
ber_skip_data(
	BerElement *ber,
	ber_len_t len )
{
	ber_len_t	actuallen, nleft;

	assert( ber != NULL );
	assert( LBER_VALID( ber ) );

	nleft = ber_pvt_ber_remaining( ber );
	actuallen = nleft < len ? nleft : len;
	ber->ber_ptr += actuallen;
	ber->ber_tag = *(unsigned char *)ber->ber_ptr;

	return( (ber_slen_t) actuallen );
}
コード例 #15
0
ファイル: io.c プロジェクト: FarazShaikh/LikewiseSMB2
int
ber_flush2( Sockbuf *sb, BerElement *ber, int freeit )
{
	ber_len_t	towrite;
	ber_slen_t	rc;

	assert( sb != NULL );
	assert( ber != NULL );

	assert( SOCKBUF_VALID( sb ) );
	assert( LBER_VALID( ber ) );

	if ( ber->ber_rwptr == NULL ) {
		ber->ber_rwptr = ber->ber_buf;
	}
	towrite = ber->ber_ptr - ber->ber_rwptr;

	if ( sb->sb_debug ) {
		ber_log_printf( LDAP_DEBUG_TRACE, sb->sb_debug,
			"ber_flush2: %ld bytes to sd %ld%s\n",
			towrite, (long) sb->sb_fd,
			ber->ber_rwptr != ber->ber_buf ?  " (re-flush)" : "" );
		ber_log_bprint( LDAP_DEBUG_BER, sb->sb_debug,
			ber->ber_rwptr, towrite );
	}

	while ( towrite > 0 ) {
#ifdef LBER_TRICKLE
		sleep(1);
		rc = ber_int_sb_write( sb, ber->ber_rwptr, 1 );
#else
		rc = ber_int_sb_write( sb, ber->ber_rwptr, towrite );
#endif
		if ( rc <= 0 ) {
			if ( freeit & LBER_FLUSH_FREE_ON_ERROR ) ber_free( ber, 1 );
			return -1;
		}
		towrite -= rc;
		ber->ber_rwptr += rc;
	} 

	if ( freeit & LBER_FLUSH_FREE_ON_SUCCESS ) ber_free( ber, 1 );

	return 0;
}
コード例 #16
0
ファイル: io.c プロジェクト: FarazShaikh/LikewiseSMB2
void
ber_free_buf( BerElement *ber )
{
	Seqorset *s, *next;

	assert( LBER_VALID( ber ) );

	if ( ber->ber_buf) ber_memfree_x( ber->ber_buf, ber->ber_memctx );

	for( s = ber->ber_sos ; s != NULL ; s = next ) {
		next = s->sos_next;
		ber_memfree_x( s, ber->ber_memctx );
	}

	ber->ber_buf = NULL;
	ber->ber_sos = NULL;
	ber->ber_valid = LBER_UNINITIALIZED;
}
コード例 #17
0
ファイル: io.c プロジェクト: bagel/openldap-ga
BerElement *
ber_alloc_t( int options )
{
	BerElement	*ber;

	ber = (BerElement *) LBER_CALLOC( 1, sizeof(BerElement) );

	if ( ber == NULL ) {
		return NULL;
	}

	ber->ber_valid = LBER_VALID_BERELEMENT;
	ber->ber_tag = LBER_DEFAULT;
	ber->ber_options = options;
	ber->ber_debug = ber_int_debug;

	assert( LBER_VALID( ber ) );
	return ber;
}
コード例 #18
0
ファイル: encode.c プロジェクト: szakats/bzflag_mirror
int
ber_put_bitstring(
	BerElement *ber,
	LDAP_CONST char *str,
	ber_len_t blen /* in bits */,
	ber_tag_t tag )
{
	int				taglen, lenlen;
	ber_len_t		len;
	unsigned char	unusedbits;

	assert( ber != NULL );
	assert( str != NULL );

	assert( LBER_VALID( ber ) );

	if ( tag == LBER_DEFAULT ) {
		tag = LBER_BITSTRING;
	}

	if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) {
		return -1;
	}

	len = ( blen + 7 ) / 8;
	unusedbits = (unsigned char) ((len * 8) - blen);
	if ( (lenlen = ber_put_len( ber, len + 1, 0 )) == -1 ) {
		return -1;
	}

	if ( ber_write( ber, (char *)&unusedbits, 1, 0 ) != 1 ) {
		return -1;
	}

	if ( (ber_len_t) ber_write( ber, str, len, 0 ) != len ) {
		return -1;
	}

	/* return length of tag + length + unused bit count + contents */
	return taglen + 1 + lenlen + len;
}
コード例 #19
0
ファイル: io.c プロジェクト: bagel/openldap-ga
/*
 * Read from the ber buffer.  The caller must maintain ber->ber_tag.
 * Do not use to read whole tags.  See ber_get_tag() and ber_skip_data().
 */
ber_slen_t
ber_read(
	BerElement *ber,
	char *buf,
	ber_len_t len )
{
	ber_len_t	actuallen, nleft;

	assert( ber != NULL );
	assert( buf != NULL );
	assert( LBER_VALID( ber ) );

	nleft = ber_pvt_ber_remaining( ber );
	actuallen = nleft < len ? nleft : len;

	AC_MEMCPY( buf, ber->ber_ptr, actuallen );

	ber->ber_ptr += actuallen;

	return( (ber_slen_t) actuallen );
}
コード例 #20
0
ファイル: encode.c プロジェクト: szakats/bzflag_mirror
int
ber_put_null( BerElement *ber, ber_tag_t tag )
{
	int	taglen;

	assert( ber != NULL );
	assert( LBER_VALID( ber ) );

	if ( tag == LBER_DEFAULT ) {
		tag = LBER_NULL;
	}

	if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) {
		return -1;
	}

	if ( ber_put_len( ber, 0, 0 ) != 1 ) {
		return -1;
	}

	return taglen + 1;
}
コード例 #21
0
ファイル: options.c プロジェクト: cptaffe/openldap
int
ber_set_option(
	void	*item,
	int		option,
	LDAP_CONST void	*invalue)
{
	BerElement *ber;
	Sockbuf *sb;

	if(invalue == NULL) {
		/* no place to set from */
		ber_errno = LBER_ERROR_PARAM;
		return LBER_OPT_ERROR;
	}

	if(item == NULL) {
		switch ( option ) {
		case LBER_OPT_BER_DEBUG:
			ber_int_debug = * (const int *) invalue;
			return LBER_OPT_SUCCESS;

		case LBER_OPT_LOG_PRINT_FN:
			ber_pvt_log_print = (BER_LOG_PRINT_FN) invalue;
			return LBER_OPT_SUCCESS;

		case LBER_OPT_LOG_PRINT_FILE:
			ber_pvt_err_file = (void *) invalue;
			return LBER_OPT_SUCCESS;

		case LBER_OPT_MEMORY_INUSE:
			/* The memory inuse is a global variable on kernal implementations.
			 * This means that memory debug is shared by all LDAP processes
			 * so for this variable to have much meaning, only one LDAP process
			 * should be running and memory inuse should be initialized to zero
			 * using the lber_set_option() function during startup.
			 * The counter is not accurate for multithreaded applications.
			 */
#ifdef LDAP_MEMORY_DEBUG
			ber_int_meminuse = * (int *) invalue;
			return LBER_OPT_SUCCESS;
#else
			return LBER_OPT_ERROR;
#endif
		case LBER_OPT_MEMORY_FNS:
			if ( ber_int_memory_fns == NULL )
			{
				const BerMemoryFunctions *f =
					(const BerMemoryFunctions *) invalue;
				/* make sure all functions are provided */
				if(!( f->bmf_malloc && f->bmf_calloc
					&& f->bmf_realloc && f->bmf_free ))
				{
					ber_errno = LBER_ERROR_PARAM;
					return LBER_OPT_ERROR;
				}

				ber_int_memory_fns = &ber_int_memory_fns_datum;

				AC_MEMCPY(ber_int_memory_fns, f,
					 sizeof(BerMemoryFunctions));

				return LBER_OPT_SUCCESS;
			}
			break;

		case LBER_OPT_LOG_PROC:
			ber_int_log_proc = (BER_LOG_FN)invalue;
			return LBER_OPT_SUCCESS;
		}

		ber_errno = LBER_ERROR_PARAM;
		return LBER_OPT_ERROR;
	}

	ber = item;
	sb = item;

	switch(option) {
	case LBER_OPT_BER_OPTIONS:
		assert( LBER_VALID( ber ) );
		ber->ber_options = * (const int *) invalue;
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_DEBUG:
		assert( LBER_VALID( ber ) );
		ber->ber_debug = * (const int *) invalue;
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_REMAINING_BYTES:
		assert( LBER_VALID( ber ) );
		ber->ber_end = &ber->ber_ptr[* (const ber_len_t *) invalue];
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_TOTAL_BYTES:
		assert( LBER_VALID( ber ) );
		ber->ber_end = &ber->ber_buf[* (const ber_len_t *) invalue];
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_BYTES_TO_WRITE:
		assert( LBER_VALID( ber ) );
		ber->ber_ptr = &ber->ber_buf[* (const ber_len_t *) invalue];
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_MEMCTX:
		assert( LBER_VALID( ber ) );
		ber->ber_memctx = *(void **)invalue;
		return LBER_OPT_SUCCESS;

	default:
		/* bad param */
		ber_errno = LBER_ERROR_PARAM;
		break;
	}

	return LBER_OPT_ERROR;
}
コード例 #22
0
ファイル: sasl.c プロジェクト: BackupTheBerlios/wl530g-svn
int
ldap_sasl_bind(
	LDAP			*ld,
	LDAP_CONST char	*dn,
	LDAP_CONST char	*mechanism,
	struct berval	*cred,
	LDAPControl		**sctrls,
	LDAPControl		**cctrls,
	int				*msgidp )
{
	BerElement	*ber;
	int rc;

#ifdef NEW_LOGGING
	LDAP_LOG ( TRANSPORT, ENTRY, "ldap_sasl_bind\n", 0, 0, 0 );
#else
	Debug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 );
#endif

	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( msgidp != NULL );

	/* check client controls */
	rc = ldap_int_client_controls( ld, cctrls );
	if( rc != LDAP_SUCCESS ) return rc;

	if( mechanism == LDAP_SASL_SIMPLE ) {
		if( dn == NULL && cred != NULL && cred->bv_len ) {
			/* use default binddn */
			dn = ld->ld_defbinddn;
		}

	} else if( ld->ld_version < LDAP_VERSION3 ) {
		ld->ld_errno = LDAP_NOT_SUPPORTED;
		return ld->ld_errno;
	}

	if ( dn == NULL ) {
		dn = "";
	}

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	assert( LBER_VALID( ber ) );

	if( mechanism == LDAP_SASL_SIMPLE ) {
		/* simple bind */
		rc = ber_printf( ber, "{it{istON}" /*}*/,
			++ld->ld_msgid, LDAP_REQ_BIND,
			ld->ld_version, dn, LDAP_AUTH_SIMPLE,
			cred );
		
	} else if ( cred == NULL || cred->bv_val == NULL ) {
		/* SASL bind w/o creditials */
		rc = ber_printf( ber, "{it{ist{sN}N}" /*}*/,
			++ld->ld_msgid, LDAP_REQ_BIND,
			ld->ld_version, dn, LDAP_AUTH_SASL,
			mechanism );

	} else {
		/* SASL bind w/ creditials */
		rc = ber_printf( ber, "{it{ist{sON}N}" /*}*/,
			++ld->ld_msgid, LDAP_REQ_BIND,
			ld->ld_version, dn, LDAP_AUTH_SASL,
			mechanism, cred );
	}

	if( rc == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( -1 );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return ld->ld_errno;
	}


	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber );

	if(*msgidp < 0)
		return ld->ld_errno;

	return LDAP_SUCCESS;
}
コード例 #23
0
static ber_tag_t
try_read1msg(
	LDAP *ld,
	ber_int_t msgid,
	int all,
	LDAPConn **lcp,
	LDAPMessage **result )
{
	BerElement	*ber;
	LDAPMessage	*newmsg, *l, *prev;
	ber_int_t	id;
	int		idx;
	ber_tag_t	tag;
	ber_len_t	len;
	int		foundit = 0;
	LDAPRequest	*lr, *tmplr, dummy_lr = { 0 };
	LDAPConn	*lc;
	BerElement	tmpber;
	int		rc, refer_cnt, hadref, simple_request;
	ber_int_t	lderr;

#ifdef LDAP_CONNECTIONLESS
	LDAPMessage	*tmp = NULL, *chain_head = NULL;
	int		moremsgs = 0, isv2 = 0;
#endif

	assert( ld != NULL );
	assert( lcp != NULL );
	assert( *lcp != NULL );
	
#ifdef LDAP_R_COMPILE
	LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
#endif

	Debug( LDAP_DEBUG_TRACE, "read1msg: ld %p msgid %d all %d\n",
		(void *)ld, msgid, all );

	lc = *lcp;

retry:
	if ( lc->lconn_ber == NULL ) {
		lc->lconn_ber = ldap_alloc_ber_with_options( ld );

		if ( lc->lconn_ber == NULL ) {
			return -1;
		}
	}

	ber = lc->lconn_ber;
	assert( LBER_VALID (ber) );

	/* get the next message */
	sock_errset(0);
#ifdef LDAP_CONNECTIONLESS
	if ( LDAP_IS_UDP(ld) ) {
		struct sockaddr from;
		ber_int_sb_read( lc->lconn_sb, &from, sizeof(struct sockaddr) );
		if ( ld->ld_options.ldo_version == LDAP_VERSION2 ) isv2 = 1;
	}
nextresp3:
#endif
	tag = ber_get_next( lc->lconn_sb, &len, ber );
	switch ( tag ) {
	case LDAP_TAG_MESSAGE:
		/*
	 	 * We read a complete message.
	 	 * The connection should no longer need this ber.
	 	 */
		lc->lconn_ber = NULL;
		break;

	case LBER_DEFAULT:
#ifdef LDAP_DEBUG		   
		Debug( LDAP_DEBUG_CONNS,
			"ber_get_next failed.\n", 0, 0, 0 );
#endif		   
#ifdef EWOULDBLOCK			
		if ( sock_errno() == EWOULDBLOCK ) return LDAP_MSG_X_KEEP_LOOKING;
#endif
#ifdef EAGAIN
		if ( sock_errno() == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING;
#endif
		ld->ld_errno = LDAP_SERVER_DOWN;
#ifdef LDAP_R_COMPILE
		ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
		ldap_free_connection( ld, lc, 1, 0 );
#ifdef LDAP_R_COMPILE
		ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
		lc = *lcp = NULL;
		return -1;

	default:
		ld->ld_errno = LDAP_LOCAL_ERROR;
		return -1;
	}

	/* message id */
	if ( ber_get_int( ber, &id ) == LBER_ERROR ) {
		ber_free( ber, 1 );
		ld->ld_errno = LDAP_DECODING_ERROR;
		return( -1 );
	}

	/* id == 0 iff unsolicited notification message (RFC 4511) */

	/* if it's been abandoned, toss it */
	if ( id > 0 ) {
		if ( ldap_abandoned( ld, id, &idx ) ) {
			/* the message type */
			tag = ber_peek_tag( ber, &len );
			switch ( tag ) {
			case LDAP_RES_SEARCH_ENTRY:
			case LDAP_RES_SEARCH_REFERENCE:
			case LDAP_RES_INTERMEDIATE:
			case LBER_ERROR:
				break;

			default:
				/* there's no need to keep the id
				 * in the abandoned list any longer */
				ldap_mark_abandoned( ld, id, idx );
				break;
			}

			Debug( LDAP_DEBUG_ANY,
				"abandoned/discarded ld %p msgid %ld message type %s\n",
				(void *)ld, (long)id, ldap_int_msgtype2str( tag ) );

retry_ber:
			ber_free( ber, 1 );
			if ( ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) {
				goto retry;
			}
			return( LDAP_MSG_X_KEEP_LOOKING );	/* continue looking */
		}

		lr = ldap_find_request_by_msgid( ld, id );
		if ( lr == NULL ) {
			const char	*msg = "unknown";

			/* the message type */
			tag = ber_peek_tag( ber, &len );
			switch ( tag ) {
			case LBER_ERROR:
				break;

			default:
				msg = ldap_int_msgtype2str( tag );
				break;
			}

			Debug( LDAP_DEBUG_ANY,
				"no request for response on ld %p msgid %ld message type %s (tossing)\n",
				(void *)ld, (long)id, msg );

			goto retry_ber;
		}

#ifdef LDAP_CONNECTIONLESS
		if ( LDAP_IS_UDP(ld) && isv2 ) {
			ber_scanf(ber, "x{");
		}
nextresp2:
#endif
	}

	/* the message type */
	tag = ber_peek_tag( ber, &len );
	if ( tag == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		ber_free( ber, 1 );
		return( -1 );
	}

	Debug( LDAP_DEBUG_TRACE,
		"read1msg: ld %p msgid %ld message type %s\n",
		(void *)ld, (long)lr->lr_msgid, ldap_int_msgtype2str( tag ) );

	if ( id == 0 ) {
		/* unsolicited notification message (RFC 4511) */
		if ( tag != LDAP_RES_EXTENDED ) {
			/* toss it */
			goto retry_ber;

			/* strictly speaking, it's an error; from RFC 4511:

4.4.  Unsolicited Notification

   An unsolicited notification is an LDAPMessage sent from the server to
   the client that is not in response to any LDAPMessage received by the
   server.  It is used to signal an extraordinary condition in the
   server or in the LDAP session between the client and the server.  The
   notification is of an advisory nature, and the server will not expect
   any response to be returned from the client.

   The unsolicited notification is structured as an LDAPMessage in which
   the messageID is zero and protocolOp is set to the extendedResp
   choice using the ExtendedResponse type (See Section 4.12).  The
   responseName field of the ExtendedResponse always contains an LDAPOID
   that is unique for this notification.

			 * however, since unsolicited responses
			 * are of advisory nature, better
			 * toss it, right now
			 */

#if 0
			ld->ld_errno = LDAP_DECODING_ERROR;
			ber_free( ber, 1 );
			return( -1 );
#endif
		}

		lr = &dummy_lr;
	}

	id = lr->lr_origid;
	refer_cnt = 0;
	hadref = simple_request = 0;
	rc = LDAP_MSG_X_KEEP_LOOKING;	/* default is to keep looking (no response found) */
	lr->lr_res_msgtype = tag;

	/*
	 * Check for V3 search reference
	 */
	if ( tag == LDAP_RES_SEARCH_REFERENCE ) {
		if ( ld->ld_version > LDAP_VERSION2 ) {
			/* This is a V3 search reference */
			if ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) ||
					lr->lr_parent != NULL )
			{
				char **refs = NULL;
				tmpber = *ber;

				/* Get the referral list */
				if ( ber_scanf( &tmpber, "{v}", &refs ) == LBER_ERROR ) {
					rc = LDAP_DECODING_ERROR;

				} else {
					/* Note: refs array is freed by ldap_chase_v3referrals */
					refer_cnt = ldap_chase_v3referrals( ld, lr, refs,
						1, &lr->lr_res_error, &hadref );
					if ( refer_cnt > 0 ) {
						/* successfully chased reference */
						/* If haven't got end search, set chasing referrals */
						if ( lr->lr_status != LDAP_REQST_COMPLETED ) {
							lr->lr_status = LDAP_REQST_CHASINGREFS;
							Debug( LDAP_DEBUG_TRACE,
								"read1msg:  search ref chased, "
								"mark request chasing refs, "
								"id = %d\n",
								lr->lr_msgid, 0, 0 );
						}
					}
				}
			}
		}

	} else if ( tag != LDAP_RES_SEARCH_ENTRY && tag != LDAP_RES_INTERMEDIATE ) {
		/* All results that just return a status, i.e. don't return data
		 * go through the following code.  This code also chases V2 referrals
		 * and checks if all referrals have been chased.
		 */
		char		*lr_res_error = NULL;

		tmpber = *ber; 	/* struct copy */
		if ( ber_scanf( &tmpber, "{eAA", &lderr,
				&lr->lr_res_matched, &lr_res_error )
				!= LBER_ERROR )
		{
			if ( lr_res_error != NULL ) {
				if ( lr->lr_res_error != NULL ) {
					(void)ldap_append_referral( ld, &lr->lr_res_error, lr_res_error );
					LDAP_FREE( (char *)lr_res_error );

				} else {
					lr->lr_res_error = lr_res_error;
				}
				lr_res_error = NULL;
			}

			/* Do we need to check for referrals? */
			if ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) ||
					lr->lr_parent != NULL )
			{
				char		**refs = NULL;
				ber_len_t	len;

				/* Check if V3 referral */
				if ( ber_peek_tag( &tmpber, &len ) == LDAP_TAG_REFERRAL ) {
					if ( ld->ld_version > LDAP_VERSION2 ) {
						/* Get the referral list */
						if ( ber_scanf( &tmpber, "{v}", &refs) == LBER_ERROR) {
							rc = LDAP_DECODING_ERROR;
							lr->lr_status = LDAP_REQST_COMPLETED;
							Debug( LDAP_DEBUG_TRACE,
								"read1msg: referral decode error, "
								"mark request completed, ld %p msgid %d\n",
								(void *)ld, lr->lr_msgid, 0 );

						} else {
							/* Chase the referral 
							 * refs array is freed by ldap_chase_v3referrals
							 */
							refer_cnt = ldap_chase_v3referrals( ld, lr, refs,
								0, &lr->lr_res_error, &hadref );
							lr->lr_status = LDAP_REQST_COMPLETED;
							Debug( LDAP_DEBUG_TRACE,
								"read1msg: referral %s chased, "
								"mark request completed, ld %p msgid %d\n",
								refer_cnt > 0 ? "" : "not",
								(void *)ld, lr->lr_msgid);
							if ( refer_cnt < 0 ) {
								refer_cnt = 0;
							}
						}
					}
				} else {
					switch ( lderr ) {
					case LDAP_SUCCESS:
					case LDAP_COMPARE_TRUE:
					case LDAP_COMPARE_FALSE:
						break;

					default:
						if ( lr->lr_res_error == NULL ) {
							break;
						}

						/* pedantic, should never happen */
						if ( lr->lr_res_error[ 0 ] == '\0' ) {
							LDAP_FREE( lr->lr_res_error );
							lr->lr_res_error = NULL;
							break;	
						}

						/* V2 referrals are in error string */
						refer_cnt = ldap_chase_referrals( ld, lr,
							&lr->lr_res_error, -1, &hadref );
						lr->lr_status = LDAP_REQST_COMPLETED;
						Debug( LDAP_DEBUG_TRACE,
							"read1msg:  V2 referral chased, "
							"mark request completed, id = %d\n",
							lr->lr_msgid, 0, 0 );
						break;
					}
				}
			}

			/* save errno, message, and matched string */
			if ( !hadref || lr->lr_res_error == NULL ) {
				lr->lr_res_errno =
					lderr == LDAP_PARTIAL_RESULTS
					? LDAP_SUCCESS : lderr;

			} else if ( ld->ld_errno != LDAP_SUCCESS ) {
				lr->lr_res_errno = ld->ld_errno;

			} else {
				lr->lr_res_errno = LDAP_PARTIAL_RESULTS;
			}
		}

		/* in any case, don't leave any lr_res_error 'round */
		if ( lr_res_error ) {
			LDAP_FREE( lr_res_error );
		}

		Debug( LDAP_DEBUG_TRACE,
			"read1msg: ld %p %d new referrals\n",
			(void *)ld, refer_cnt, 0 );

		if ( refer_cnt != 0 ) {	/* chasing referrals */
			ber_free( ber, 1 );
			ber = NULL;
			if ( refer_cnt < 0 ) {
				ldap_return_request( ld, lr, 0 );
				return( -1 );	/* fatal error */
			}
			lr->lr_res_errno = LDAP_SUCCESS; /* sucessfully chased referral */

		} else {
			if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) {
				/* request without any referrals */
				simple_request = ( hadref ? 0 : 1 );

			} else {
				/* request with referrals or child request */
				ber_free( ber, 1 );
				ber = NULL;
			}

			lr->lr_status = LDAP_REQST_COMPLETED; /* declare this request done */
			Debug( LDAP_DEBUG_TRACE,
				"read1msg:  mark request completed, ld %p msgid %d\n",
				(void *)ld, lr->lr_msgid, 0);
			while ( lr->lr_parent != NULL ) {
				merge_error_info( ld, lr->lr_parent, lr );

				lr = lr->lr_parent;
				if ( --lr->lr_outrefcnt > 0 ) {
					break;	/* not completely done yet */
				}
			}

			/* Check if all requests are finished, lr is now parent */
			tmplr = lr;
			if ( tmplr->lr_status == LDAP_REQST_COMPLETED ) {
				for ( tmplr = lr->lr_child;
					tmplr != NULL;
					tmplr = tmplr->lr_refnext )
				{
					if ( tmplr->lr_status != LDAP_REQST_COMPLETED ) break;
				}
			}

			/* This is the parent request if the request has referrals */
			if ( lr->lr_outrefcnt <= 0 &&
				lr->lr_parent == NULL &&
				tmplr == NULL )
			{
				id = lr->lr_msgid;
				tag = lr->lr_res_msgtype;
				Debug( LDAP_DEBUG_TRACE, "request done: ld %p msgid %ld\n",
					(void *)ld, (long) id, 0 );
				Debug( LDAP_DEBUG_TRACE,
					"res_errno: %d, res_error: <%s>, "
					"res_matched: <%s>\n",
					lr->lr_res_errno,
					lr->lr_res_error ? lr->lr_res_error : "",
					lr->lr_res_matched ? lr->lr_res_matched : "" );
				if ( !simple_request ) {
					ber_free( ber, 1 );
					ber = NULL;
					if ( build_result_ber( ld, &ber, lr )
					    == LBER_ERROR )
					{
						rc = -1; /* fatal error */
					}
				}

				if ( lr != &dummy_lr ) {
					ldap_return_request( ld, lr, 1 );
				}
				lr = NULL;
			}

			/*
			 * RF 4511 unsolicited (id == 0) responses
			 * shouldn't necessarily end the connection
			 */
			if ( lc != NULL && id != 0 ) {
#ifdef LDAP_R_COMPILE
				ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
				ldap_free_connection( ld, lc, 0, 1 );
#ifdef LDAP_R_COMPILE
				ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
				lc = *lcp = NULL;
			}
		}
	}

	if ( lr != NULL ) {
		if ( lr != &dummy_lr ) {
			ldap_return_request( ld, lr, 0 );
		}
		lr = NULL;
	}

	if ( ber == NULL ) {
		return( rc );
	}

	/* try to handle unsolicited responses as appropriate */
	if ( id == 0 && msgid > LDAP_RES_UNSOLICITED ) {
		int	is_nod = 0;

		tag = ber_peek_tag( &tmpber, &len );

		/* we have a res oid */
		if ( tag == LDAP_TAG_EXOP_RES_OID ) {
			static struct berval	bv_nod = BER_BVC( LDAP_NOTICE_OF_DISCONNECTION );
			struct berval		resoid = BER_BVNULL;

			if ( ber_scanf( &tmpber, "m", &resoid ) == LBER_ERROR ) {
				ld->ld_errno = LDAP_DECODING_ERROR;
				ber_free( ber, 1 );
				return -1;
			}

			assert( !BER_BVISEMPTY( &resoid ) );

			is_nod = ber_bvcmp( &resoid, &bv_nod ) == 0;

			tag = ber_peek_tag( &tmpber, &len );
		}

#if 0 /* don't need right now */
		/* we have res data */
		if ( tag == LDAP_TAG_EXOP_RES_VALUE ) {
			struct berval resdata;

			if ( ber_scanf( &tmpber, "m", &resdata ) == LBER_ERROR ) {
				ld->ld_errno = LDAP_DECODING_ERROR;
				ber_free( ber, 0 );
				return ld->ld_errno;
			}

			/* use it... */
		}
#endif

		/* handle RFC 4511 "Notice of Disconnection" locally */

		if ( is_nod ) {
			if ( tag == LDAP_TAG_EXOP_RES_VALUE ) {
				ld->ld_errno = LDAP_DECODING_ERROR;
				ber_free( ber, 1 );
				return -1;
			}

			/* get rid of the connection... */
			if ( lc != NULL ) {
#ifdef LDAP_R_COMPILE
				ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
				ldap_free_connection( ld, lc, 0, 1 );
#ifdef LDAP_R_COMPILE
				ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
				lc = *lcp = NULL;
			}

			/* need to return -1, because otherwise
			 * a valid result is expected */
			return -1;
		}
	}

	/* make a new ldap message */
	newmsg = (LDAPMessage *) LDAP_CALLOC( 1, sizeof(LDAPMessage) );
	if ( newmsg == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return( -1 );
	}
	newmsg->lm_msgid = (int)id;
	newmsg->lm_msgtype = tag;
	newmsg->lm_ber = ber;
	newmsg->lm_chain_tail = newmsg;

#ifdef LDAP_CONNECTIONLESS
	/* CLDAP replies all fit in a single datagram. In LDAPv2 RFC1798
	 * the responses are all a sequence wrapped in one message. In
	 * LDAPv3 each response is in its own message. The datagram must
	 * end with a SearchResult. We can't just parse each response in
	 * separate calls to try_read1msg because the header info is only
	 * present at the beginning of the datagram, not at the beginning
	 * of each response. So parse all the responses at once and queue
	 * them up, then pull off the first response to return to the
	 * caller when all parsing is complete.
	 */
	if ( LDAP_IS_UDP(ld) ) {
		/* If not a result, look for more */
		if ( tag != LDAP_RES_SEARCH_RESULT ) {
			int ok = 0;
			moremsgs = 1;
			if (isv2) {
				/* LDAPv2: dup the current ber, skip past the current
				 * response, and see if there are any more after it.
				 */
				ber = ber_dup( ber );
				ber_scanf( ber, "x" );
				if ( ber_peek_tag( ber, &len ) != LBER_DEFAULT ) {
					/* There's more - dup the ber buffer so they can all be
					 * individually freed by ldap_msgfree.
					 */
					struct berval bv;
					ber_get_option( ber, LBER_OPT_BER_REMAINING_BYTES, &len );
					bv.bv_val = LDAP_MALLOC( len );
					if ( bv.bv_val ) {
						ok = 1;
						ber_read( ber, bv.bv_val, len );
						bv.bv_len = len;
						ber_init2( ber, &bv, ld->ld_lberoptions );
					}
				}
			} else {
				/* LDAPv3: Just allocate a new ber. Since this is a buffered
				 * datagram, if the sockbuf is readable we still have data
				 * to parse.
				 */
				ber = ldap_alloc_ber_with_options( ld );
				if ( ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) ok = 1;
			}
			/* set up response chain */
			if ( tmp == NULL ) {
				newmsg->lm_next = ld->ld_responses;
				ld->ld_responses = newmsg;
				chain_head = newmsg;
			} else {
				tmp->lm_chain = newmsg;
			}
			chain_head->lm_chain_tail = newmsg;
			tmp = newmsg;
			/* "ok" means there's more to parse */
			if ( ok ) {
				if ( isv2 ) {
					goto nextresp2;

				} else {
					goto nextresp3;
				}
			} else {
				/* got to end of datagram without a SearchResult. Free
				 * our dup'd ber, but leave any buffer alone. For v2 case,
				 * the previous response is still using this buffer. For v3,
				 * the new ber has no buffer to free yet.
				 */
				ber_free( ber, 0 );
				return -1;
			}
		} else if ( moremsgs ) {
		/* got search result, and we had multiple responses in 1 datagram.
		 * stick the result onto the end of the chain, and then pull the
		 * first response off the head of the chain.
		 */
			tmp->lm_chain = newmsg;
			chain_head->lm_chain_tail = newmsg;
			*result = chkResponseList( ld, msgid, all );
			ld->ld_errno = LDAP_SUCCESS;
			return( (*result)->lm_msgtype );
		}
	}
#endif /* LDAP_CONNECTIONLESS */

	/* is this the one we're looking for? */
	if ( msgid == LDAP_RES_ANY || id == msgid ) {
		if ( all == LDAP_MSG_ONE
			|| ( newmsg->lm_msgtype != LDAP_RES_SEARCH_RESULT
			    	&& newmsg->lm_msgtype != LDAP_RES_SEARCH_ENTRY
			  	&& newmsg->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) )
		{
			*result = newmsg;
			ld->ld_errno = LDAP_SUCCESS;
			return( tag );

		} else if ( newmsg->lm_msgtype == LDAP_RES_SEARCH_RESULT) {
			foundit = 1;	/* return the chain later */
		}
	}

	/* 
	 * if not, we must add it to the list of responses.  if
	 * the msgid is already there, it must be part of an existing
	 * search response.
	 */

	prev = NULL;
	for ( l = ld->ld_responses; l != NULL; l = l->lm_next ) {
		if ( l->lm_msgid == newmsg->lm_msgid ) {
			break;
		}
		prev = l;
	}

	/* not part of an existing search response */
	if ( l == NULL ) {
		if ( foundit ) {
			*result = newmsg;
			goto exit;
		}

		newmsg->lm_next = ld->ld_responses;
		ld->ld_responses = newmsg;
		goto exit;
	}

	Debug( LDAP_DEBUG_TRACE, "adding response ld %p msgid %ld type %ld:\n",
		(void *)ld, (long) newmsg->lm_msgid, (long) newmsg->lm_msgtype );

	/* part of a search response - add to end of list of entries */
	l->lm_chain_tail->lm_chain = newmsg;
	l->lm_chain_tail = newmsg;

	/* return the whole chain if that's what we were looking for */
	if ( foundit ) {
		if ( prev == NULL ) {
			ld->ld_responses = l->lm_next;
		} else {
			prev->lm_next = l->lm_next;
		}
		*result = l;
	}

exit:
	if ( foundit ) {
		ld->ld_errno = LDAP_SUCCESS;
		return( tag );
	}
	if ( lc && ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) {
		goto retry;
	}
	return( LDAP_MSG_X_KEEP_LOOKING );	/* continue looking */
}


static ber_tag_t
build_result_ber( LDAP *ld, BerElement **bp, LDAPRequest *lr )
{
	ber_len_t	len;
	ber_tag_t	tag;
	ber_int_t	along;
	BerElement *ber;

	*bp = NULL;
	ber = ldap_alloc_ber_with_options( ld );

	if( ber == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return LBER_ERROR;
	}

	if ( ber_printf( ber, "{it{ess}}", lr->lr_msgid,
		lr->lr_res_msgtype, lr->lr_res_errno,
		lr->lr_res_matched ? lr->lr_res_matched : "",
		lr->lr_res_error ? lr->lr_res_error : "" ) == -1 )
	{
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( LBER_ERROR );
	}

	ber_reset( ber, 1 );

	if ( ber_skip_tag( ber, &len ) == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		ber_free( ber, 1 );
		return( LBER_ERROR );
	}

	if ( ber_get_enum( ber, &along ) == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		ber_free( ber, 1 );
		return( LBER_ERROR );
	}

	tag = ber_peek_tag( ber, &len );

	if ( tag == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		ber_free( ber, 1 );
		return( LBER_ERROR );
	}

	*bp = ber;
	return tag;
}
コード例 #24
0
ファイル: encode.c プロジェクト: szakats/bzflag_mirror
static int
ber_put_int_or_enum(
	BerElement *ber,
	ber_int_t num,
	ber_tag_t tag )
{
	int rc;
	int	i, j, sign, taglen, lenlen;
	ber_len_t	len;
	ber_uint_t	unum, mask;
	unsigned char netnum[sizeof(ber_uint_t)];

	assert( ber != NULL );
	assert( LBER_VALID( ber ) );

	sign = (num < 0);
	unum = num;	/* Bit fiddling should be done with unsigned values */

	/*
	 * high bit is set - look for first non-all-one byte
	 * high bit is clear - look for first non-all-zero byte
	 */
	i = BER_TOP_BYTE(ber_int_t);
	mask = BER_TOP_MASK(ber_uint_t);
	for ( ; i > 0; i-- ) {
		if ( sign ) {
			/* not all ones */
			if ( (unum & mask) != mask ) break;
		} else {
			/* not all zero */
			if ( unum & mask ) break;
		}
		mask >>= 8;
	}

	/*
	 * we now have the "leading byte".  if the high bit on this
	 * byte matches the sign bit, we need to "back up" a byte.
	 */
	mask = (unum & ((ber_uint_t)0x80U << (i * 8)));
	if ( (mask && !sign) || (sign && !mask) ) {
		i++;
	}

	len = i + 1;

	if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) {
		return -1;
	}

	if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 ) {
		return -1;
	}
	i++;

	for( j=i-1; j>=0; j-- ) {
		netnum[j] = (unsigned char)(unum & 0xffU);
		unum >>= 8;
	}

	rc = ber_write( ber, (char *) netnum, i, 0 );

	/* length of tag + length + contents */
	return rc == i ? taglen + lenlen + i : -1;
}
コード例 #25
0
ファイル: options.c プロジェクト: cptaffe/openldap
int
ber_get_option(
	void	*item,
	int		option,
	void	*outvalue)
{
	const BerElement *ber;
	const Sockbuf *sb;

	if(outvalue == NULL) {
		/* no place to get to */
		ber_errno = LBER_ERROR_PARAM;
		return LBER_OPT_ERROR;
	}

	if(item == NULL) {
		switch ( option ) {
		case LBER_OPT_BER_DEBUG:
			* (int *) outvalue = ber_int_debug;
			return LBER_OPT_SUCCESS;

		case LBER_OPT_MEMORY_INUSE:
			/* The memory inuse is a global variable on kernal implementations.
			 * This means that memory debug is shared by all LDAP processes
			 * so for this variable to have much meaning, only one LDAP process
			 * should be running and memory inuse should be initialized to zero
			 * using the lber_set_option() function during startup.
			 * The counter is not accurate for multithreaded ldap applications.
			 */
#ifdef LDAP_MEMORY_DEBUG
			* (int *) outvalue = ber_int_meminuse;
			return LBER_OPT_SUCCESS;
#else
			return LBER_OPT_ERROR;
#endif

		case LBER_OPT_LOG_PRINT_FILE:
			*((FILE**)outvalue) = (FILE*)ber_pvt_err_file;
			return LBER_OPT_SUCCESS;
		}

		ber_errno = LBER_ERROR_PARAM;
		return LBER_OPT_ERROR;
	}

	ber = item;
	sb = item;

	switch(option) {
	case LBER_OPT_BER_OPTIONS:
		assert( LBER_VALID( ber ) );
		* (int *) outvalue = ber->ber_options;
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_DEBUG:
		assert( LBER_VALID( ber ) );
		* (int *) outvalue = ber->ber_debug;
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_REMAINING_BYTES:
		assert( LBER_VALID( ber ) );
		*((ber_len_t *) outvalue) = ber_pvt_ber_remaining(ber);
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_TOTAL_BYTES:
		assert( LBER_VALID( ber ) );
		*((ber_len_t *) outvalue) = ber_pvt_ber_total(ber);
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_BYTES_TO_WRITE:
		assert( LBER_VALID( ber ) );
		*((ber_len_t *) outvalue) = ber_pvt_ber_write(ber);
		return LBER_OPT_SUCCESS;

	case LBER_OPT_BER_MEMCTX:
		assert( LBER_VALID( ber ) );
		*((void **) outvalue) = ber->ber_memctx;
		return LBER_OPT_SUCCESS;
	
	default:
		/* bad param */
		ber_errno = LBER_ERROR_PARAM;
		break;
	}

	return LBER_OPT_ERROR;
}
コード例 #26
0
ファイル: io.c プロジェクト: FarazShaikh/LikewiseSMB2
int
ber_realloc( BerElement *ber, ber_len_t len )
{
	ber_len_t	total;
	Seqorset	*s;
	long		off;
	char		*oldbuf;

	assert( ber != NULL );
	assert( len > 0 );
	assert( LBER_VALID( ber ) );

	total = ber_pvt_ber_total( ber );

#define LBER_EXBUFSIZ	4060 /* a few words less than 2^N for binary buddy */
#if defined( LBER_EXBUFSIZ ) && LBER_EXBUFSIZ > 0
# ifndef notdef
	/* don't realloc by small amounts */
	total += len < LBER_EXBUFSIZ ? LBER_EXBUFSIZ : len;
# else
	{	/* not sure what value this adds */
		ber_len_t have = (total + (LBER_EXBUFSIZE - 1)) / LBER_EXBUFSIZ;
		ber_len_t need = (len + (LBER_EXBUFSIZ - 1)) / LBER_EXBUFSIZ;
		total = ( have + need ) * LBER_EXBUFSIZ;
	}
# endif
#else
	total += len;	/* realloc just what's needed */
#endif

	oldbuf = ber->ber_buf;

	ber->ber_buf = (char *) ber_memrealloc_x( oldbuf, total, ber->ber_memctx );
	
	if ( ber->ber_buf == NULL ) {
		ber->ber_buf = oldbuf;
		return( -1 );
	}

	ber->ber_end = ber->ber_buf + total;

	/*
	 * If the stinking thing was moved, we need to go through and
	 * reset all the sos and ber pointers.	Offsets would've been
	 * a better idea... oh well.
	 */

	if ( ber->ber_buf != oldbuf ) {
		ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf);

		for ( s = ber->ber_sos; s != NULL; s = s->sos_next ) {
			off = s->sos_first - oldbuf;
			s->sos_first = ber->ber_buf + off;

			off = s->sos_ptr - oldbuf;
			s->sos_ptr = ber->ber_buf + off;
		}
	}

	return( 0 );
}