/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of Michigan at Ann Arbor. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*/
/* io.c - ber general i/o routines */
#include "lber-int.h"
# ifdef macintosh
/*
*/
# define BerWrite( sb, b, l ) tcpwrite( sb->sb_sd, (unsigned char *)(b), (l<MAX_WRITE)? l : MAX_WRITE )
# else /* macintosh */
/*
* 32-bit Windows Socket API (under Windows NT or Windows 95)
*/
# else /* _WIN32 */
/*
*/
# endif /* _WIN32 */
# endif /* macintosh */
#ifndef udp_read
#endif /* udp_read */
#ifdef LDAP_DEBUG
int lber_debug;
#endif
/*
* function prototypes
*/
struct lextiof_socket_private *arg );
struct lextiof_socket_private *arg );
/*
* internal global structure for memory allocation callback functions
*/
/*
* buffered read from "sb".
* returns value of first character read on success and -1 on error.
*/
static int
{
#ifdef CLDAP
int addrlen;
#endif /* CLDAP */
READBUFSIZ )) == NULL ) {
return( -1 );
}
}
#ifdef CLDAP
#ifdef LDAP_DEBUG
if ( lber_debug ) {
rc );
ber_err_print( msg );
}
#endif /* LDAP_DEBUG */
#else /* CLDAP */
rc = -1;
#endif /* CLDAP */
} else {
} else {
}
}
if ( rc > 0 ) {
}
return( -1 );
}
static ber_int_t
{
int c;
while ( len > 0 ) {
if ( nread > 0 )
break;
return( c );
}
*buf++ = c;
nread++;
len--;
}
return( nread );
}
/*
* Note: ber_read() only uses the ber_end and ber_ptr elements of ber.
* Functions like ber_get_tag(), ber_skip_tag, and ber_peek_tag() rely on
* that fact, so if this code is changed to use any additional elements of
* the ber structure, those functions will need to be changed as well.
*/
{
}
/*
* enlarge the ber buffer.
* return 0 on success, -1 on error.
*/
int
{
Seqorset *s;
char *oldbuf;
== NULL ) {
return( -1 );
}
} else {
/* transition to malloc'd buffer */
return( -1 );
}
/* copy existing data into new malloc'd buffer */
} else {
return( -1 );
}
}
}
/*
* 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.
*/
}
}
return( 0 );
}
/*
* returns "len" on success and -1 on failure.
*/
{
return( -1 );
}
return( len );
} else {
return( -1 );
}
return( len );
}
}
void
{
if ( freebuf &&
}
NSLBERI_FREE( (char *) ber );
}
}
/*
* return >= 0 on success, -1 on failure.
*/
int
{
/* we will use the ber_rwptr to continue an exited flush,
so if rwptr is not within the buffer we return an error. */
return( -1 );
}
#ifdef LDAP_DEBUG
if ( lber_debug ) {
: "" );
ber_err_print( msg );
if ( lber_debug > 1 )
}
#endif
return( (int)rc );
}
}
#endif
nwritten = 0;
do {
#ifdef CLDAP
#else /* CLDAP */
rc = -1;
#endif /* CLDAP */
if ( rc <= 0 )
return( -1 );
/* fake error if write was not atomic */
#endif
return( -1 );
}
} else {
<= 0 ) {
return( -1 );
}
} else {
return( -1 );
}
}
}
} while ( towrite > 0 );
if ( freeit )
return( 0 );
}
/* we pre-allocate a buffer to save the extra malloc later */
{
return( NULL );
}
/*
* for compatibility with the C LDAP API standard, we recognize
* LBER_USE_DER as LBER_OPT_USE_DER. See lber.h for a bit more info.
*/
if ( options & LBER_USE_DER ) {
options &= ~LBER_USE_DER;
}
return( ber );
}
{
return( ber_alloc_t( 0 ) );
}
{
return( ber_alloc_t( LBER_OPT_USE_DER ) );
}
{
return( NULL );
return( new );
}
void
{
/*
* For compatibility with the C LDAP API standard, we recognize
* LBER_USE_DER as LBER_OPT_USE_DER. See lber.h for a bit more info.
*/
if ( options & LBER_USE_DER ) {
options &= ~LBER_USE_DER;
}
}
void
{
if ( was_writing ) {
} else {
}
}
#ifdef LDAP_DEBUG
void
{
ber_err_print( msg );
if ( inout == 1 ) {
ber_err_print( msg );
} else {
ber_err_print( msg );
}
}
void
{
ber_err_print ( "*** sos dump ***\n" );
while ( sos != NULLSEQORSET ) {
ber_err_print( msg );
ber_err_print( msg );
}
ber_err_print( "*** end dump ***\n" );
}
#endif
/* return the tag - LBER_DEFAULT returned means trouble */
static ber_tag_t
{
unsigned char xbyte;
char *tagp;
int i;
return( LBER_DEFAULT );
}
return( (ber_uint_t) xbyte );
}
for ( i = 1; i < sizeof(ber_int_t); i++ ) {
return( LBER_DEFAULT );
if ( ! (xbyte & LBER_MORE_TAG_MASK) )
break;
}
/* tag too big! */
if ( i == sizeof(ber_int_t) )
return( LBER_DEFAULT );
/* want leading, not trailing 0's */
}
{
unsigned char lc;
#ifdef LDAP_DEBUG
if ( lber_debug )
ber_err_print( "ber_get_next\n" );
#endif
/*
* Any ber element looks like this: tag length contents.
* Assuming everything's ok, we return the tag byte (we
* can assume a single byte), return the length in len,
* and the rest of the undecoded element in buf.
*
* Assumptions:
* 1) small tags (less than 128)
* 2) definite lengths
* 3) primitive encodings used whenever possible
*/
/*
* first time through - malloc the buffer, set up ptrs, and
* read the tag and the length and as much of the rest as we can
*/
/*
* First, we read the tag.
*/
return( LBER_DEFAULT );
}
/*
* Next, read the length. The first byte contains the length
* of the length. If bit 8 is set, the length is the long
* form, otherwise it's the short form. We don't allow a
* length that's greater than what we can hold in an unsigned
* long.
*/
return( LBER_DEFAULT );
}
if ( lc & 0x80 ) {
if ( noctets > sizeof(ber_uint_t) )
return( LBER_DEFAULT );
noctets ) {
return( LBER_DEFAULT );
}
} else {
}
/*
* Finally, malloc a buffer for the contents and read it in.
* It's this buffer that's passed to all the other ber decoding
* routines.
*/
return( LBER_DEFAULT );
}
#endif /* DOS && !_WIN32 */
return( LBER_DEFAULT );
}
== NULL ) {
return( LBER_DEFAULT );
}
}
do {
return( LBER_DEFAULT );
}
} while ( toread > 0 );
#ifdef LDAP_DEBUG
if ( lber_debug ) {
ber_err_print( msg );
if ( lber_debug > 1 )
}
#endif
}
Sockbuf *
{
}
void
{
if ( p != NULL ) {
#ifdef LDAP_SASLIO_HOOKS
if ( p->sb_sasl_ctx != NULL)
sasl_dispose(&p->sb_sasl_ctx);
if ( p->sb_sasl_ibuf != NULL) {
NSLBERI_FREE( p->sb_sasl_ibuf );
}
#endif
}
NSLBERI_FREE(p);
}
}
/*
* return 0 on success and -1 on error
*/
int
{
/*
* memory allocation callbacks are global, so it is OK to pass
* NULL for ber. Handle this as a special case.
*/
if ( option == LBER_OPT_MEMALLOC_FN_PTRS ) {
/* struct copy */
return( 0 );
}
/*
* lber_debug is global, so it is OK to pass
* NULL for ber. Handle this as a special case.
*/
if ( option == LBER_OPT_DEBUG_LEVEL ) {
#ifdef LDAP_DEBUG
lber_debug = *(int *)value;
#endif
return( 0 );
}
/*
* all the rest require a non-NULL ber
*/
if ( !NSLBERI_VALID_BERELEMENT_POINTER( ber )) {
return( -1 );
}
switch ( option ) {
case LBER_OPT_USE_DER:
} else {
}
break;
case LBER_OPT_REMAINING_BYTES:
break;
case LBER_OPT_TOTAL_BYTES:
break;
case LBER_OPT_BYTES_TO_WRITE:
break;
default:
return( -1 );
}
return( 0 );
}
/*
* return 0 on success and -1 on error
*/
int
{
/*
* memory callocation callbacks are global, so it is OK to pass
* NULL for ber. Handle this as a special case
*/
if ( option == LBER_OPT_MEMALLOC_FN_PTRS ) {
/* struct copy */
return( 0 );
}
/*
* lber_debug is global, so it is OK to pass
* NULL for ber. Handle this as a special case.
*/
if ( option == LBER_OPT_DEBUG_LEVEL ) {
#ifdef LDAP_DEBUG
*(int *)value = lber_debug;
#endif
return( 0 );
}
/*
* all the rest require a non-NULL ber
*/
if ( !NSLBERI_VALID_BERELEMENT_POINTER( ber )) {
return( -1 );
}
switch ( option ) {
case LBER_OPT_USE_DER:
break;
case LBER_OPT_REMAINING_BYTES:
break;
case LBER_OPT_TOTAL_BYTES:
break;
case LBER_OPT_BYTES_TO_WRITE:
break;
default:
return( -1 );
}
return( 0 );
}
/*
* return 0 on success and -1 on error
*/
int
{
if ( !NSLBERI_VALID_SOCKBUF_POINTER( sb )) {
return( -1 );
}
switch ( option ) {
/* FALL */
case LBER_SOCKBUF_OPT_TO_FILE:
} else {
}
break;
case LBER_SOCKBUF_OPT_DESC:
break;
break;
case LBER_SOCKBUF_OPT_READ_FN:
break;
break;
sizeof(sb->sb_ext_io_fns ));
} else if ( extiofns->lbextiofn_size
== LBER_X_EXTIO_FNS_SIZE ) {
/* struct copy */
} else {
return( -1 );
}
break;
default:
return( -1 );
}
return( 0 );
}
/*
* return 0 on success and -1 on error
*/
int
{
if ( !NSLBERI_VALID_SOCKBUF_POINTER( sb )) {
return( -1 );
}
switch ( option ) {
break;
case LBER_SOCKBUF_OPT_TO_FILE:
break;
case LBER_SOCKBUF_OPT_DESC:
break;
break;
case LBER_SOCKBUF_OPT_READ_FN:
*((LDAP_IOF_READ_CALLBACK **) value)
break;
*((LDAP_IOF_WRITE_CALLBACK **) value)
break;
!= LBER_X_EXTIO_FNS_SIZE ) {
return( -1 );
}
/* struct copy */
break;
default:
return( -1 );
}
return( 0 );
}
/* new dboreham code below: */
struct byte_buffer {
unsigned char *p;
int offset;
int length;
};
/* This call allocates us a BerElement structure plus some extra memory.
* It returns a pointer to the BerElement, plus a pointer to the extra memory.
* This routine also allocates a ber data buffer within the same block, thus
* saving a call to calloc later when we read data.
*/
void*
{
/* Make sure mem size requested is aligned */
if (0 != ( size & 0x03 )) {
}
return NULL;
}
return (void*)mem;
}
void
{
}
NSLBERI_FREE( buf );
}
static int
{
/* copy up to bytes_to_read bytes into the caller's buffer, return the number of bytes copied */
int bytes_to_copy = 0;
} else {
}
if (1 == bytes_to_copy) {
*return_buffer = *(b->p+b->offset++);
} else
if (0 == bytes_to_copy) {
;
} else
{
b->offset += bytes_to_copy;
}
return bytes_to_copy;
}
/* return the tag - LBER_DEFAULT returned means trouble */
static ber_tag_t
{
unsigned char xbyte;
char *tagp;
int i;
return( LBER_DEFAULT );
}
return( (ber_uint_t) xbyte );
}
for ( i = 1; i < sizeof(ber_int_t); i++ ) {
return( LBER_DEFAULT );
if ( ! (xbyte & LBER_MORE_TAG_MASK) )
break;
}
/* tag too big! */
if ( i == sizeof(ber_int_t) )
return( LBER_DEFAULT );
/* want leading, not trailing 0's */
}
/* Like ber_get_next, but from a byte buffer the caller already has. */
/* Bytes_Scanned returns the number of bytes we actually looked at in the buffer. */
/* ber_get_next_buffer is now implemented in terms of ber_get_next_buffer_ext */
/* and is here for backward compatibility. This new function allows us to pass */
/* the Sockbuf structure along */
{
Bytes_Scanned, NULL));
}
{
unsigned char lc;
/*
* Any ber element looks like this: tag length contents.
* Assuming everything's ok, we return the tag byte (we
* can assume a single byte), return the length in len,
* and the rest of the undecoded element in buf.
*
* Assumptions:
* 1) small tags (less than 128)
* 2) definite lengths
* 3) primitive encodings used whenever possible
*/
/*
* first time through - malloc the buffer, set up ptrs, and
* read the tag and the length and as much of the rest as we can
*/
/*
* First, we read the tag.
*/
goto premature_exit;
}
/*
* Next, read the length. The first byte contains the length
* of the length. If bit 8 is set, the length is the long
* form, otherwise it's the short form. We don't allow a
* length that's greater than what we can hold in an unsigned
* long.
*/
goto premature_exit;
}
if ( lc & 0x80 ) {
if ( noctets > sizeof(ber_uint_t) )
goto premature_exit;
goto premature_exit;
}
} else {
}
/*
* Finally, malloc a buffer for the contents and read it in.
* It's this buffer that's passed to all the other ber decoding
* routines.
*/
goto premature_exit;
}
#endif /* DOS && !_WIN32 */
return( LBER_DEFAULT );
}
goto premature_exit;
}
}
do {
goto premature_exit;
}
} while ( toread > 0 );
/*
* we're here because we hit the end of the buffer before seeing
* all of the PDU
*/
return(LBER_DEFAULT);
}
/* The ber_flatten routine allocates a struct berval whose contents
* are a BER encoding taken from the ber argument. The bvPtr pointer
* points to the returned berval, which must be freed using
* ber_bvfree(). This routine returns 0 on success and -1 on error.
* The use of ber_flatten on a BerElement in which all '{' and '}'
* format modifiers have not been properly matched can result in a
* berval whose contents are not a valid BER encoding.
* Note that the ber_ptr is not modified.
*/
int
{
/* allocate a struct berval */
== NULL ) {
return( -1 );
}
/*
* Copy everything from the BerElement's ber_buf to ber_ptr
* into the berval structure.
*/
} else {
ber_bvfree( new );
return( -1 );
}
}
/* set bvPtr pointer to point to the returned berval */
return( 0 );
}
/*
* The ber_init function constructs and returns a new BerElement
* containing a copy of the data in the bv argument. ber_init
* returns the null pointer on error.
*/
{
/* construct BerElement */
/* copy data from the bv argument into BerElement */
/* XXXmcs: had to cast unsigned long bv_len to long */
return( NULL );
}
}
/*
* reset ber_ptr back to the beginning of buffer so that this new
* and initialized ber element can be READ
*/
/*
* return a ptr to a new BerElement containing a copy of the data
* in the bv argument or a null pointer on error
*/
return( ber );
}
/*
* memory allocation functions.
*/
void *
{
}
void *
{
}
void *
{
}
void
{
} else {
}
}
/*
******************************************************************************
* functions to bridge the gap between new extended I/O functions that are
* installed using ber_sockbuf_set_option( ..., LBER_SOCKBUF_OPT_EXT_IO_FNS,
* ... ).
*
* the basic strategy is to use the new extended arg to hold a pointer to the
* Sockbuf itself so we can find the old functions and call them.
* note that the integer socket s passed in is not used. we use the sb_sd
* from the Sockbuf itself because it is the correct type.
*/
static int
struct lextiof_socket_private *arg )
{
}
static int
struct lextiof_socket_private *arg )
{
}
/*
* Install I/O compatiblity functions. This can't fail.
*/
static void
{
}
/*
* end of compat I/O functions
******************************************************************************
*/