10Sstevel@tonic-gate /*
2*12023SDoug.Leavitt@Sun.COM * CDDL HEADER START
3*12023SDoug.Leavitt@Sun.COM *
4*12023SDoug.Leavitt@Sun.COM * The contents of this file are subject to the terms of the
5*12023SDoug.Leavitt@Sun.COM * Common Development and Distribution License (the "License").
6*12023SDoug.Leavitt@Sun.COM * You may not use this file except in compliance with the License.
7*12023SDoug.Leavitt@Sun.COM *
8*12023SDoug.Leavitt@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12023SDoug.Leavitt@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*12023SDoug.Leavitt@Sun.COM * See the License for the specific language governing permissions
11*12023SDoug.Leavitt@Sun.COM * and limitations under the License.
12*12023SDoug.Leavitt@Sun.COM *
13*12023SDoug.Leavitt@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*12023SDoug.Leavitt@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12023SDoug.Leavitt@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*12023SDoug.Leavitt@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*12023SDoug.Leavitt@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*12023SDoug.Leavitt@Sun.COM *
19*12023SDoug.Leavitt@Sun.COM * CDDL HEADER END
20*12023SDoug.Leavitt@Sun.COM */
21*12023SDoug.Leavitt@Sun.COM
22*12023SDoug.Leavitt@Sun.COM /*
23*12023SDoug.Leavitt@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate
280Sstevel@tonic-gate /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
290Sstevel@tonic-gate *
300Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public License
310Sstevel@tonic-gate * Version 1.0 (the "NPL"); you may not use this file except in
320Sstevel@tonic-gate * compliance with the NPL. You may obtain a copy of the NPL at
330Sstevel@tonic-gate * http://www.mozilla.org/NPL/
340Sstevel@tonic-gate *
350Sstevel@tonic-gate * Software distributed under the NPL is distributed on an "AS IS" basis,
360Sstevel@tonic-gate * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
370Sstevel@tonic-gate * for the specific language governing rights and limitations under the
380Sstevel@tonic-gate * NPL.
390Sstevel@tonic-gate *
400Sstevel@tonic-gate * The Initial Developer of this code under the NPL is Netscape
410Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are
420Sstevel@tonic-gate * Copyright (C) 1998 Netscape Communications Corporation. All Rights
430Sstevel@tonic-gate * Reserved.
440Sstevel@tonic-gate */
450Sstevel@tonic-gate
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate * Copyright (c) 1990 Regents of the University of Michigan.
480Sstevel@tonic-gate * All rights reserved.
490Sstevel@tonic-gate *
500Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted
510Sstevel@tonic-gate * provided that this notice is preserved and that due credit is given
520Sstevel@tonic-gate * to the University of Michigan at Ann Arbor. The name of the University
530Sstevel@tonic-gate * may not be used to endorse or promote products derived from this
540Sstevel@tonic-gate * software without specific prior written permission. This software
550Sstevel@tonic-gate * is provided ``as is'' without express or implied warranty.
560Sstevel@tonic-gate */
570Sstevel@tonic-gate /* io.c - ber general i/o routines */
580Sstevel@tonic-gate
590Sstevel@tonic-gate #include "lber-int.h"
600Sstevel@tonic-gate
610Sstevel@tonic-gate #define bergetc( sb, len ) ( sb->sb_ber.ber_end > sb->sb_ber.ber_ptr ? \
620Sstevel@tonic-gate (unsigned char)*sb->sb_ber.ber_ptr++ : \
630Sstevel@tonic-gate ber_filbuf( sb, len ))
640Sstevel@tonic-gate
650Sstevel@tonic-gate # ifdef macintosh
660Sstevel@tonic-gate /*
670Sstevel@tonic-gate * MacTCP/OpenTransport
680Sstevel@tonic-gate */
690Sstevel@tonic-gate # define read( s, b, l ) tcpread( s, 0, (unsigned char *)b, l, NULL )
700Sstevel@tonic-gate # define MAX_WRITE 65535
710Sstevel@tonic-gate # define BerWrite( sb, b, l ) tcpwrite( sb->sb_sd, (unsigned char *)(b), (l<MAX_WRITE)? l : MAX_WRITE )
720Sstevel@tonic-gate # else /* macintosh */
730Sstevel@tonic-gate # if defined(_WIN32) || defined(_WINDOWS) || defined(XP_OS2)
740Sstevel@tonic-gate /*
750Sstevel@tonic-gate * 32-bit Windows Socket API (under Windows NT or Windows 95)
760Sstevel@tonic-gate */
770Sstevel@tonic-gate # define read( s, b, l ) recv( s, b, l, 0 )
780Sstevel@tonic-gate # define BerWrite( s, b, l ) send( s->sb_sd, b, l, 0 )
790Sstevel@tonic-gate # else /* _WIN32 */
800Sstevel@tonic-gate /*
810Sstevel@tonic-gate * everything else (Unix/BSD 4.3 socket API)
820Sstevel@tonic-gate */
830Sstevel@tonic-gate # define BerWrite( sb, b, l ) write( sb->sb_sd, b, l )
840Sstevel@tonic-gate # define udp_read( sb, b, l, al ) recvfrom(sb->sb_sd, (char *)b, l, 0, \
850Sstevel@tonic-gate (struct sockaddr *)sb->sb_fromaddr, \
860Sstevel@tonic-gate (al = sizeof(struct sockaddr), &al))
870Sstevel@tonic-gate # define udp_write( sb, b, l ) sendto(sb->sb_sd, (char *)(b), l, 0, \
880Sstevel@tonic-gate (struct sockaddr *)sb->sb_useaddr, sizeof(struct sockaddr))
890Sstevel@tonic-gate # endif /* _WIN32 */
900Sstevel@tonic-gate # endif /* macintosh */
910Sstevel@tonic-gate
920Sstevel@tonic-gate #ifndef udp_read
930Sstevel@tonic-gate #define udp_read( sb, b, l, al ) CLDAP NOT SUPPORTED
940Sstevel@tonic-gate #define udp_write( sb, b, l ) CLDAP NOT SUPPORTED
950Sstevel@tonic-gate #endif /* udp_read */
960Sstevel@tonic-gate
970Sstevel@tonic-gate #define EXBUFSIZ 1024
980Sstevel@tonic-gate
990Sstevel@tonic-gate #ifdef LDAP_DEBUG
1000Sstevel@tonic-gate int lber_debug;
1010Sstevel@tonic-gate #endif
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate /*
1040Sstevel@tonic-gate * function prototypes
1050Sstevel@tonic-gate */
1060Sstevel@tonic-gate static void nslberi_install_compat_io_fns( Sockbuf *sb );
1070Sstevel@tonic-gate static int nslberi_extread_compat( int s, void *buf, int len,
1080Sstevel@tonic-gate struct lextiof_socket_private *arg );
1090Sstevel@tonic-gate static int nslberi_extwrite_compat( int s, const void *buf, int len,
1100Sstevel@tonic-gate struct lextiof_socket_private *arg );
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate /*
1140Sstevel@tonic-gate * internal global structure for memory allocation callback functions
1150Sstevel@tonic-gate */
1160Sstevel@tonic-gate static struct lber_memalloc_fns nslberi_memalloc_fns;
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate /*
1200Sstevel@tonic-gate * buffered read from "sb".
1210Sstevel@tonic-gate * returns value of first character read on success and -1 on error.
1220Sstevel@tonic-gate */
1230Sstevel@tonic-gate static int
ber_filbuf(Sockbuf * sb,ber_slen_t len)1240Sstevel@tonic-gate ber_filbuf( Sockbuf *sb, ber_slen_t len )
1250Sstevel@tonic-gate {
1260Sstevel@tonic-gate ssize_t rc;
1270Sstevel@tonic-gate #ifdef CLDAP
1280Sstevel@tonic-gate int addrlen;
1290Sstevel@tonic-gate #endif /* CLDAP */
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate if ( sb->sb_ber.ber_buf == NULL ) {
1320Sstevel@tonic-gate if ( (sb->sb_ber.ber_buf = (char *)NSLBERI_MALLOC(
1330Sstevel@tonic-gate READBUFSIZ )) == NULL ) {
1340Sstevel@tonic-gate return( -1 );
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate sb->sb_ber.ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER;
1370Sstevel@tonic-gate sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf;
1380Sstevel@tonic-gate sb->sb_ber.ber_end = sb->sb_ber.ber_buf;
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate if ( sb->sb_naddr > 0 ) {
1420Sstevel@tonic-gate #ifdef CLDAP
1430Sstevel@tonic-gate rc = udp_read(sb, sb->sb_ber.ber_buf, READBUFSIZ, addrlen );
1440Sstevel@tonic-gate #ifdef LDAP_DEBUG
1450Sstevel@tonic-gate if ( lber_debug ) {
1460Sstevel@tonic-gate char msg[80];
1470Sstevel@tonic-gate sprintf( msg, "ber_filbuf udp_read %d bytes\n",
1480Sstevel@tonic-gate rc );
1490Sstevel@tonic-gate ber_err_print( msg );
1500Sstevel@tonic-gate if ( lber_debug > 1 && rc > 0 )
1510Sstevel@tonic-gate lber_bprint( sb->sb_ber.ber_buf, rc );
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate #endif /* LDAP_DEBUG */
1540Sstevel@tonic-gate #else /* CLDAP */
1550Sstevel@tonic-gate rc = -1;
1560Sstevel@tonic-gate #endif /* CLDAP */
1570Sstevel@tonic-gate } else {
1580Sstevel@tonic-gate if ( sb->sb_ext_io_fns.lbextiofn_read != NULL ) {
1590Sstevel@tonic-gate rc = sb->sb_ext_io_fns.lbextiofn_read(
1600Sstevel@tonic-gate sb->sb_sd, sb->sb_ber.ber_buf,
1610Sstevel@tonic-gate ((sb->sb_options & LBER_SOCKBUF_OPT_NO_READ_AHEAD)
1620Sstevel@tonic-gate && (len < READBUFSIZ)) ? len : READBUFSIZ,
1630Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_socket_arg );
1640Sstevel@tonic-gate } else {
1650Sstevel@tonic-gate rc = read( sb->sb_sd, sb->sb_ber.ber_buf,
1660Sstevel@tonic-gate ((sb->sb_options & LBER_SOCKBUF_OPT_NO_READ_AHEAD)
1670Sstevel@tonic-gate && (len < READBUFSIZ)) ? len : READBUFSIZ );
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate if ( rc > 0 ) {
1720Sstevel@tonic-gate sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf + 1;
1730Sstevel@tonic-gate sb->sb_ber.ber_end = sb->sb_ber.ber_buf + rc;
1740Sstevel@tonic-gate return( (unsigned char)*sb->sb_ber.ber_buf );
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate return( -1 );
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate static ber_int_t
BerRead(Sockbuf * sb,char * buf,ber_slen_t len)1820Sstevel@tonic-gate BerRead( Sockbuf *sb, char *buf, ber_slen_t len )
1830Sstevel@tonic-gate {
1840Sstevel@tonic-gate int c;
1850Sstevel@tonic-gate ber_int_t nread = 0;
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate while ( len > 0 ) {
1880Sstevel@tonic-gate if ( (c = bergetc( sb, len )) < 0 ) {
1890Sstevel@tonic-gate if ( nread > 0 )
1900Sstevel@tonic-gate break;
1910Sstevel@tonic-gate return( c );
1920Sstevel@tonic-gate }
1930Sstevel@tonic-gate *buf++ = c;
1940Sstevel@tonic-gate nread++;
1950Sstevel@tonic-gate len--;
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate return( nread );
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate /*
2030Sstevel@tonic-gate * Note: ber_read() only uses the ber_end and ber_ptr elements of ber.
2040Sstevel@tonic-gate * Functions like ber_get_tag(), ber_skip_tag, and ber_peek_tag() rely on
2050Sstevel@tonic-gate * that fact, so if this code is changed to use any additional elements of
2060Sstevel@tonic-gate * the ber structure, those functions will need to be changed as well.
2070Sstevel@tonic-gate */
2080Sstevel@tonic-gate ber_int_t
2090Sstevel@tonic-gate LDAP_CALL
ber_read(BerElement * ber,char * buf,ber_len_t len)2100Sstevel@tonic-gate ber_read( BerElement *ber, char *buf, ber_len_t len )
2110Sstevel@tonic-gate {
2120Sstevel@tonic-gate ber_len_t actuallen;
2130Sstevel@tonic-gate ber_uint_t nleft;
2140Sstevel@tonic-gate
2150Sstevel@tonic-gate nleft = ber->ber_end - ber->ber_ptr;
2160Sstevel@tonic-gate actuallen = nleft < len ? nleft : len;
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate SAFEMEMCPY( buf, ber->ber_ptr, (size_t)actuallen );
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate ber->ber_ptr += actuallen;
2210Sstevel@tonic-gate
2220Sstevel@tonic-gate return( (ber_int_t)actuallen );
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate /*
2260Sstevel@tonic-gate * enlarge the ber buffer.
2270Sstevel@tonic-gate * return 0 on success, -1 on error.
2280Sstevel@tonic-gate */
2290Sstevel@tonic-gate int
nslberi_ber_realloc(BerElement * ber,ber_len_t len)2300Sstevel@tonic-gate nslberi_ber_realloc( BerElement *ber, ber_len_t len )
2310Sstevel@tonic-gate {
2320Sstevel@tonic-gate ber_uint_t need, have, total;
2330Sstevel@tonic-gate size_t have_bytes;
2340Sstevel@tonic-gate Seqorset *s;
2350Sstevel@tonic-gate ber_int_t off;
2360Sstevel@tonic-gate char *oldbuf;
2370Sstevel@tonic-gate
2380Sstevel@tonic-gate have_bytes = ber->ber_end - ber->ber_buf;
2390Sstevel@tonic-gate have = have_bytes / EXBUFSIZ;
2400Sstevel@tonic-gate need = (len < EXBUFSIZ ? 1 : (len + (EXBUFSIZ - 1)) / EXBUFSIZ);
2410Sstevel@tonic-gate total = have * EXBUFSIZ + need * EXBUFSIZ;
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate oldbuf = ber->ber_buf;
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate if (ber->ber_buf == NULL) {
2460Sstevel@tonic-gate if ( (ber->ber_buf = (char *)NSLBERI_MALLOC( (size_t)total ))
2470Sstevel@tonic-gate == NULL ) {
2480Sstevel@tonic-gate return( -1 );
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER;
2510Sstevel@tonic-gate } else {
2520Sstevel@tonic-gate if ( ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER ) {
2530Sstevel@tonic-gate /* transition to malloc'd buffer */
2540Sstevel@tonic-gate if ( (ber->ber_buf = (char *)NSLBERI_MALLOC(
2550Sstevel@tonic-gate (size_t)total )) == NULL ) {
2560Sstevel@tonic-gate return( -1 );
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER;
2590Sstevel@tonic-gate /* copy existing data into new malloc'd buffer */
2600Sstevel@tonic-gate SAFEMEMCPY( ber->ber_buf, oldbuf, have_bytes );
2610Sstevel@tonic-gate } else {
2620Sstevel@tonic-gate if ( (ber->ber_buf = (char *)NSLBERI_REALLOC(
2630Sstevel@tonic-gate ber->ber_buf,(size_t)total )) == NULL ) {
2640Sstevel@tonic-gate return( -1 );
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate ber->ber_end = ber->ber_buf + total;
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate /*
2720Sstevel@tonic-gate * If the stinking thing was moved, we need to go through and
2730Sstevel@tonic-gate * reset all the sos and ber pointers. Offsets would've been
2740Sstevel@tonic-gate * a better idea... oh well.
2750Sstevel@tonic-gate */
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate if ( ber->ber_buf != oldbuf ) {
2780Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf);
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate for ( s = ber->ber_sos; s != NULLSEQORSET; s = s->sos_next ) {
2810Sstevel@tonic-gate off = s->sos_first - oldbuf;
2820Sstevel@tonic-gate s->sos_first = ber->ber_buf + off;
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate off = s->sos_ptr - oldbuf;
2850Sstevel@tonic-gate s->sos_ptr = ber->ber_buf + off;
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate return( 0 );
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate /*
2930Sstevel@tonic-gate * returns "len" on success and -1 on failure.
2940Sstevel@tonic-gate */
2950Sstevel@tonic-gate ber_int_t
2960Sstevel@tonic-gate LDAP_CALL
ber_write(BerElement * ber,char * buf,ber_len_t len,int nosos)2970Sstevel@tonic-gate ber_write( BerElement *ber, char *buf, ber_len_t len, int nosos )
2980Sstevel@tonic-gate {
2990Sstevel@tonic-gate if ( nosos || ber->ber_sos == NULL ) {
3000Sstevel@tonic-gate if ( ber->ber_ptr + len > ber->ber_end ) {
3010Sstevel@tonic-gate if ( nslberi_ber_realloc( ber, len ) != 0 )
3020Sstevel@tonic-gate return( -1 );
3030Sstevel@tonic-gate }
3040Sstevel@tonic-gate SAFEMEMCPY( ber->ber_ptr, buf, (size_t)len );
3050Sstevel@tonic-gate ber->ber_ptr += len;
3060Sstevel@tonic-gate return( len );
3070Sstevel@tonic-gate } else {
3080Sstevel@tonic-gate if ( ber->ber_sos->sos_ptr + len > ber->ber_end ) {
3090Sstevel@tonic-gate if ( nslberi_ber_realloc( ber, len ) != 0 )
3100Sstevel@tonic-gate return( -1 );
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate SAFEMEMCPY( ber->ber_sos->sos_ptr, buf, (size_t)len );
3130Sstevel@tonic-gate ber->ber_sos->sos_ptr += len;
3140Sstevel@tonic-gate ber->ber_sos->sos_clen += len;
3150Sstevel@tonic-gate return( len );
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate
3190Sstevel@tonic-gate void
3200Sstevel@tonic-gate LDAP_CALL
ber_free(BerElement * ber,int freebuf)3210Sstevel@tonic-gate ber_free( BerElement *ber, int freebuf )
3220Sstevel@tonic-gate {
3230Sstevel@tonic-gate if ( ber != NULL ) {
3240Sstevel@tonic-gate if ( freebuf &&
3250Sstevel@tonic-gate !(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER)) {
3260Sstevel@tonic-gate NSLBERI_FREE(ber->ber_buf);
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate NSLBERI_FREE( (char *) ber );
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate /*
3330Sstevel@tonic-gate * return >= 0 on success, -1 on failure.
3340Sstevel@tonic-gate */
3350Sstevel@tonic-gate int
3360Sstevel@tonic-gate LDAP_CALL
ber_flush(Sockbuf * sb,BerElement * ber,int freeit)3370Sstevel@tonic-gate ber_flush( Sockbuf *sb, BerElement *ber, int freeit )
3380Sstevel@tonic-gate {
3390Sstevel@tonic-gate ssize_t nwritten, towrite, rc;
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate if ( ber->ber_rwptr == NULL ) {
3420Sstevel@tonic-gate ber->ber_rwptr = ber->ber_buf;
3430Sstevel@tonic-gate } else if (ber->ber_rwptr >= ber->ber_end) {
3440Sstevel@tonic-gate /* we will use the ber_rwptr to continue an exited flush,
3450Sstevel@tonic-gate so if rwptr is not within the buffer we return an error. */
3460Sstevel@tonic-gate return( -1 );
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate towrite = ber->ber_ptr - ber->ber_rwptr;
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate #ifdef LDAP_DEBUG
3510Sstevel@tonic-gate if ( lber_debug ) {
3520Sstevel@tonic-gate char msg[80];
3530Sstevel@tonic-gate sprintf( msg, "ber_flush: %ld bytes to sd %ld%s\n", towrite,
3540Sstevel@tonic-gate sb->sb_sd, ber->ber_rwptr != ber->ber_buf ? " (re-flush)"
3550Sstevel@tonic-gate : "" );
3560Sstevel@tonic-gate ber_err_print( msg );
3570Sstevel@tonic-gate if ( lber_debug > 1 )
3580Sstevel@tonic-gate lber_bprint( ber->ber_rwptr, towrite );
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate #endif
3610Sstevel@tonic-gate #if !defined(macintosh) && !defined(DOS)
3620Sstevel@tonic-gate if ( sb->sb_options & (LBER_SOCKBUF_OPT_TO_FILE | LBER_SOCKBUF_OPT_TO_FILE_ONLY) ) {
3630Sstevel@tonic-gate rc = write( sb->sb_copyfd, ber->ber_buf, towrite );
3640Sstevel@tonic-gate if ( sb->sb_options & LBER_SOCKBUF_OPT_TO_FILE_ONLY ) {
3650Sstevel@tonic-gate return( (int)rc );
3660Sstevel@tonic-gate }
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate #endif
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate nwritten = 0;
3710Sstevel@tonic-gate do {
3720Sstevel@tonic-gate if (sb->sb_naddr > 0) {
3730Sstevel@tonic-gate #ifdef CLDAP
3740Sstevel@tonic-gate rc = udp_write( sb, ber->ber_buf + nwritten,
3750Sstevel@tonic-gate (size_t)towrite );
3760Sstevel@tonic-gate #else /* CLDAP */
3770Sstevel@tonic-gate rc = -1;
3780Sstevel@tonic-gate #endif /* CLDAP */
3790Sstevel@tonic-gate if ( rc <= 0 )
3800Sstevel@tonic-gate return( -1 );
3810Sstevel@tonic-gate /* fake error if write was not atomic */
3820Sstevel@tonic-gate if (rc < towrite) {
3830Sstevel@tonic-gate #if !defined( macintosh ) && !defined( DOS )
3840Sstevel@tonic-gate errno = EMSGSIZE; /* For Win32, see portable.h */
3850Sstevel@tonic-gate #endif
3860Sstevel@tonic-gate return( -1 );
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate } else {
3890Sstevel@tonic-gate if ( sb->sb_ext_io_fns.lbextiofn_write != NULL ) {
3900Sstevel@tonic-gate if ( (rc = sb->sb_ext_io_fns.lbextiofn_write(
3910Sstevel@tonic-gate sb->sb_sd, ber->ber_rwptr, (size_t)towrite,
3920Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_socket_arg ))
3930Sstevel@tonic-gate <= 0 ) {
3940Sstevel@tonic-gate return( -1 );
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate } else {
3970Sstevel@tonic-gate if ( (rc = BerWrite( sb, ber->ber_rwptr,
3980Sstevel@tonic-gate (size_t) towrite )) <= 0 ) {
3990Sstevel@tonic-gate return( -1 );
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate }
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate towrite -= rc;
4040Sstevel@tonic-gate nwritten += rc;
4050Sstevel@tonic-gate ber->ber_rwptr += rc;
4060Sstevel@tonic-gate } while ( towrite > 0 );
4070Sstevel@tonic-gate
4080Sstevel@tonic-gate if ( freeit )
4090Sstevel@tonic-gate ber_free( ber, 1 );
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate return( 0 );
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate
4150Sstevel@tonic-gate /* we pre-allocate a buffer to save the extra malloc later */
4160Sstevel@tonic-gate BerElement *
4170Sstevel@tonic-gate LDAP_CALL
ber_alloc_t(int options)4180Sstevel@tonic-gate ber_alloc_t( int options )
4190Sstevel@tonic-gate {
4200Sstevel@tonic-gate BerElement *ber;
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate if ( (ber = (BerElement*)NSLBERI_CALLOC( 1,
4230Sstevel@tonic-gate sizeof(struct berelement) + EXBUFSIZ )) == NULL ) {
4240Sstevel@tonic-gate return( NULL );
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate /*
4280Sstevel@tonic-gate * for compatibility with the C LDAP API standard, we recognize
4290Sstevel@tonic-gate * LBER_USE_DER as LBER_OPT_USE_DER. See lber.h for a bit more info.
4300Sstevel@tonic-gate */
4310Sstevel@tonic-gate if ( options & LBER_USE_DER ) {
4320Sstevel@tonic-gate options &= ~LBER_USE_DER;
4330Sstevel@tonic-gate options |= LBER_OPT_USE_DER;
4340Sstevel@tonic-gate }
4350Sstevel@tonic-gate
4360Sstevel@tonic-gate ber->ber_tag = LBER_DEFAULT;
4370Sstevel@tonic-gate ber->ber_options = options;
4380Sstevel@tonic-gate ber->ber_buf = (char*)ber + sizeof(struct berelement);
4390Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf;
4400Sstevel@tonic-gate ber->ber_end = ber->ber_buf + EXBUFSIZ;
4410Sstevel@tonic-gate ber->ber_flags = LBER_FLAG_NO_FREE_BUFFER;
4420Sstevel@tonic-gate
4430Sstevel@tonic-gate return( ber );
4440Sstevel@tonic-gate }
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate
4470Sstevel@tonic-gate BerElement *
4480Sstevel@tonic-gate LDAP_CALL
ber_alloc()4490Sstevel@tonic-gate ber_alloc()
4500Sstevel@tonic-gate {
4510Sstevel@tonic-gate return( ber_alloc_t( 0 ) );
4520Sstevel@tonic-gate }
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate BerElement *
4550Sstevel@tonic-gate LDAP_CALL
der_alloc()4560Sstevel@tonic-gate der_alloc()
4570Sstevel@tonic-gate {
4580Sstevel@tonic-gate return( ber_alloc_t( LBER_OPT_USE_DER ) );
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate
4610Sstevel@tonic-gate BerElement *
4620Sstevel@tonic-gate LDAP_CALL
ber_dup(BerElement * ber)4630Sstevel@tonic-gate ber_dup( BerElement *ber )
4640Sstevel@tonic-gate {
4650Sstevel@tonic-gate BerElement *new;
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate if ( (new = ber_alloc()) == NULL )
4680Sstevel@tonic-gate return( NULL );
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate *new = *ber;
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate return( new );
4730Sstevel@tonic-gate }
4740Sstevel@tonic-gate
4750Sstevel@tonic-gate
4760Sstevel@tonic-gate void
4770Sstevel@tonic-gate LDAP_CALL
ber_init_w_nullchar(BerElement * ber,int options)4780Sstevel@tonic-gate ber_init_w_nullchar( BerElement *ber, int options )
4790Sstevel@tonic-gate {
4800Sstevel@tonic-gate (void) memset( (char *)ber, '\0', sizeof(struct berelement) );
4810Sstevel@tonic-gate ber->ber_tag = LBER_DEFAULT;
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate /*
4840Sstevel@tonic-gate * For compatibility with the C LDAP API standard, we recognize
4850Sstevel@tonic-gate * LBER_USE_DER as LBER_OPT_USE_DER. See lber.h for a bit more info.
4860Sstevel@tonic-gate */
4870Sstevel@tonic-gate if ( options & LBER_USE_DER ) {
4880Sstevel@tonic-gate options &= ~LBER_USE_DER;
4890Sstevel@tonic-gate options |= LBER_OPT_USE_DER;
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate
4920Sstevel@tonic-gate ber->ber_options = options;
4930Sstevel@tonic-gate }
4940Sstevel@tonic-gate
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate void
4970Sstevel@tonic-gate LDAP_CALL
ber_reset(BerElement * ber,int was_writing)4980Sstevel@tonic-gate ber_reset( BerElement *ber, int was_writing )
4990Sstevel@tonic-gate {
5000Sstevel@tonic-gate if ( was_writing ) {
5010Sstevel@tonic-gate ber->ber_end = ber->ber_ptr;
5020Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf;
5030Sstevel@tonic-gate } else {
5040Sstevel@tonic-gate ber->ber_ptr = ber->ber_end;
5050Sstevel@tonic-gate }
5060Sstevel@tonic-gate
5070Sstevel@tonic-gate ber->ber_rwptr = NULL;
5080Sstevel@tonic-gate }
5090Sstevel@tonic-gate
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate #ifdef LDAP_DEBUG
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate void
ber_dump(BerElement * ber,int inout)5140Sstevel@tonic-gate ber_dump( BerElement *ber, int inout )
5150Sstevel@tonic-gate {
5160Sstevel@tonic-gate char msg[128];
5170Sstevel@tonic-gate sprintf( msg, "ber_dump: buf 0x%lx, ptr 0x%lx, rwptr 0x%lx, end 0x%lx\n",
5180Sstevel@tonic-gate ber->ber_buf, ber->ber_ptr, ber->ber_rwptr, ber->ber_end );
5190Sstevel@tonic-gate ber_err_print( msg );
5200Sstevel@tonic-gate if ( inout == 1 ) {
5210Sstevel@tonic-gate sprintf( msg, " current len %ld, contents:\n",
5220Sstevel@tonic-gate ber->ber_end - ber->ber_ptr );
5230Sstevel@tonic-gate ber_err_print( msg );
5240Sstevel@tonic-gate lber_bprint( ber->ber_ptr, ber->ber_end - ber->ber_ptr );
5250Sstevel@tonic-gate } else {
5260Sstevel@tonic-gate sprintf( msg, " current len %ld, contents:\n",
5270Sstevel@tonic-gate ber->ber_ptr - ber->ber_buf );
5280Sstevel@tonic-gate ber_err_print( msg );
5290Sstevel@tonic-gate lber_bprint( ber->ber_buf, ber->ber_ptr - ber->ber_buf );
5300Sstevel@tonic-gate }
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate void
ber_sos_dump(Seqorset * sos)5340Sstevel@tonic-gate ber_sos_dump( Seqorset *sos )
5350Sstevel@tonic-gate {
5360Sstevel@tonic-gate char msg[80];
5370Sstevel@tonic-gate ber_err_print ( "*** sos dump ***\n" );
5380Sstevel@tonic-gate while ( sos != NULLSEQORSET ) {
5390Sstevel@tonic-gate sprintf( msg, "ber_sos_dump: clen %ld first 0x%lx ptr 0x%lx\n",
5400Sstevel@tonic-gate sos->sos_clen, sos->sos_first, sos->sos_ptr );
5410Sstevel@tonic-gate ber_err_print( msg );
5420Sstevel@tonic-gate sprintf( msg, " current len %ld contents:\n",
5430Sstevel@tonic-gate sos->sos_ptr - sos->sos_first );
5440Sstevel@tonic-gate ber_err_print( msg );
5450Sstevel@tonic-gate lber_bprint( sos->sos_first, sos->sos_ptr - sos->sos_first );
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate sos = sos->sos_next;
5480Sstevel@tonic-gate }
5490Sstevel@tonic-gate ber_err_print( "*** end dump ***\n" );
5500Sstevel@tonic-gate }
5510Sstevel@tonic-gate
5520Sstevel@tonic-gate #endif
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate /* return the tag - LBER_DEFAULT returned means trouble */
5550Sstevel@tonic-gate static ber_tag_t
get_tag(Sockbuf * sb)5560Sstevel@tonic-gate get_tag( Sockbuf *sb )
5570Sstevel@tonic-gate {
5580Sstevel@tonic-gate unsigned char xbyte;
5590Sstevel@tonic-gate ber_tag_t tag;
5600Sstevel@tonic-gate char *tagp;
5610Sstevel@tonic-gate int i;
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate if ( (i = BerRead( sb, (char *) &xbyte, 1 )) != 1 ) {
5640Sstevel@tonic-gate return( LBER_DEFAULT );
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate
5670Sstevel@tonic-gate if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) {
5680Sstevel@tonic-gate return( (ber_uint_t) xbyte );
5690Sstevel@tonic-gate }
5700Sstevel@tonic-gate
5710Sstevel@tonic-gate tagp = (char *) &tag;
5720Sstevel@tonic-gate tagp[0] = xbyte;
5730Sstevel@tonic-gate for ( i = 1; i < sizeof(ber_int_t); i++ ) {
5740Sstevel@tonic-gate if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 )
5750Sstevel@tonic-gate return( LBER_DEFAULT );
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate tagp[i] = xbyte;
5780Sstevel@tonic-gate
5790Sstevel@tonic-gate if ( ! (xbyte & LBER_MORE_TAG_MASK) )
5800Sstevel@tonic-gate break;
5810Sstevel@tonic-gate }
5820Sstevel@tonic-gate
5830Sstevel@tonic-gate /* tag too big! */
5840Sstevel@tonic-gate if ( i == sizeof(ber_int_t) )
5850Sstevel@tonic-gate return( LBER_DEFAULT );
5860Sstevel@tonic-gate
5870Sstevel@tonic-gate /* want leading, not trailing 0's */
5880Sstevel@tonic-gate return( tag >> (sizeof(ber_int_t) - i - 1) );
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate ber_tag_t
5920Sstevel@tonic-gate LDAP_CALL
ber_get_next(Sockbuf * sb,ber_len_t * len,BerElement * ber)5930Sstevel@tonic-gate ber_get_next( Sockbuf *sb, ber_len_t *len, BerElement *ber )
5940Sstevel@tonic-gate {
5950Sstevel@tonic-gate ber_tag_t tag = 0;
5960Sstevel@tonic-gate ber_len_t netlen;
5970Sstevel@tonic-gate ber_uint_t toread;
5980Sstevel@tonic-gate unsigned char lc;
5990Sstevel@tonic-gate ber_int_t rc;
6000Sstevel@tonic-gate int noctets, diff;
6010Sstevel@tonic-gate
6020Sstevel@tonic-gate #ifdef LDAP_DEBUG
6030Sstevel@tonic-gate if ( lber_debug )
6040Sstevel@tonic-gate ber_err_print( "ber_get_next\n" );
6050Sstevel@tonic-gate #endif
6060Sstevel@tonic-gate
6070Sstevel@tonic-gate /*
6080Sstevel@tonic-gate * Any ber element looks like this: tag length contents.
6090Sstevel@tonic-gate * Assuming everything's ok, we return the tag byte (we
6100Sstevel@tonic-gate * can assume a single byte), return the length in len,
6110Sstevel@tonic-gate * and the rest of the undecoded element in buf.
6120Sstevel@tonic-gate *
6130Sstevel@tonic-gate * Assumptions:
6140Sstevel@tonic-gate * 1) small tags (less than 128)
6150Sstevel@tonic-gate * 2) definite lengths
6160Sstevel@tonic-gate * 3) primitive encodings used whenever possible
6170Sstevel@tonic-gate */
6180Sstevel@tonic-gate
6190Sstevel@tonic-gate /*
6200Sstevel@tonic-gate * first time through - malloc the buffer, set up ptrs, and
6210Sstevel@tonic-gate * read the tag and the length and as much of the rest as we can
6220Sstevel@tonic-gate */
6230Sstevel@tonic-gate
6240Sstevel@tonic-gate if ( ber->ber_rwptr == NULL ) {
6250Sstevel@tonic-gate /*
6260Sstevel@tonic-gate * First, we read the tag.
6270Sstevel@tonic-gate */
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate if ( (tag = get_tag( sb )) == LBER_DEFAULT ) {
6300Sstevel@tonic-gate return( LBER_DEFAULT );
6310Sstevel@tonic-gate }
6320Sstevel@tonic-gate ber->ber_tag = tag;
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate /*
6350Sstevel@tonic-gate * Next, read the length. The first byte contains the length
6360Sstevel@tonic-gate * of the length. If bit 8 is set, the length is the long
6370Sstevel@tonic-gate * form, otherwise it's the short form. We don't allow a
6380Sstevel@tonic-gate * length that's greater than what we can hold in an unsigned
6390Sstevel@tonic-gate * long.
6400Sstevel@tonic-gate */
6410Sstevel@tonic-gate
6420Sstevel@tonic-gate *len = netlen = 0;
6430Sstevel@tonic-gate if ( BerRead( sb, (char *) &lc, 1 ) != 1 ) {
6440Sstevel@tonic-gate return( LBER_DEFAULT );
6450Sstevel@tonic-gate }
6460Sstevel@tonic-gate if ( lc & 0x80 ) {
6470Sstevel@tonic-gate noctets = (lc & 0x7f);
6480Sstevel@tonic-gate if ( noctets > sizeof(ber_uint_t) )
6490Sstevel@tonic-gate return( LBER_DEFAULT );
6500Sstevel@tonic-gate diff = sizeof(ber_uint_t) - noctets;
6510Sstevel@tonic-gate if ( BerRead( sb, (char *) &netlen + diff, noctets ) !=
6520Sstevel@tonic-gate noctets ) {
6530Sstevel@tonic-gate return( LBER_DEFAULT );
6540Sstevel@tonic-gate }
6550Sstevel@tonic-gate *len = LBER_NTOHL( netlen );
6560Sstevel@tonic-gate } else {
6570Sstevel@tonic-gate *len = lc;
6580Sstevel@tonic-gate }
6590Sstevel@tonic-gate ber->ber_len = *len;
6600Sstevel@tonic-gate
6610Sstevel@tonic-gate /*
6620Sstevel@tonic-gate * Finally, malloc a buffer for the contents and read it in.
6630Sstevel@tonic-gate * It's this buffer that's passed to all the other ber decoding
6640Sstevel@tonic-gate * routines.
6650Sstevel@tonic-gate */
6660Sstevel@tonic-gate
6670Sstevel@tonic-gate #if defined( DOS ) && !( defined( _WIN32 ) || defined(XP_OS2) )
6680Sstevel@tonic-gate if ( *len > 65535 ) { /* DOS can't allocate > 64K */
6690Sstevel@tonic-gate return( LBER_DEFAULT );
6700Sstevel@tonic-gate }
6710Sstevel@tonic-gate #endif /* DOS && !_WIN32 */
6720Sstevel@tonic-gate
6730Sstevel@tonic-gate if ( ( sb->sb_options & LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE )
6740Sstevel@tonic-gate && *len > sb->sb_max_incoming ) {
6750Sstevel@tonic-gate return( LBER_DEFAULT );
6760Sstevel@tonic-gate }
6770Sstevel@tonic-gate
6780Sstevel@tonic-gate if ( (ber->ber_buf = (char *)NSLBERI_CALLOC( 1,(size_t)*len ))
6790Sstevel@tonic-gate == NULL ) {
6800Sstevel@tonic-gate return( LBER_DEFAULT );
6810Sstevel@tonic-gate }
6820Sstevel@tonic-gate ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER;
6830Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf;
6840Sstevel@tonic-gate ber->ber_end = ber->ber_buf + *len;
6850Sstevel@tonic-gate ber->ber_rwptr = ber->ber_buf;
6860Sstevel@tonic-gate }
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate toread = (uintptr_t)ber->ber_end - (uintptr_t)ber->ber_rwptr;
6890Sstevel@tonic-gate do {
6900Sstevel@tonic-gate if ( (rc = BerRead( sb, ber->ber_rwptr, (ber_int_t)toread )) <= 0 ) {
6910Sstevel@tonic-gate return( LBER_DEFAULT );
6920Sstevel@tonic-gate }
6930Sstevel@tonic-gate
6940Sstevel@tonic-gate toread -= rc;
6950Sstevel@tonic-gate ber->ber_rwptr += rc;
6960Sstevel@tonic-gate } while ( toread > 0 );
6970Sstevel@tonic-gate
6980Sstevel@tonic-gate #ifdef LDAP_DEBUG
6990Sstevel@tonic-gate if ( lber_debug ) {
7000Sstevel@tonic-gate char msg[80];
7010Sstevel@tonic-gate sprintf( msg, "ber_get_next: tag 0x%lx len %ld contents:\n",
7020Sstevel@tonic-gate tag, ber->ber_len );
7030Sstevel@tonic-gate ber_err_print( msg );
7040Sstevel@tonic-gate if ( lber_debug > 1 )
7050Sstevel@tonic-gate ber_dump( ber, 1 );
7060Sstevel@tonic-gate }
7070Sstevel@tonic-gate #endif
7080Sstevel@tonic-gate
7090Sstevel@tonic-gate *len = ber->ber_len;
7100Sstevel@tonic-gate ber->ber_rwptr = NULL;
7110Sstevel@tonic-gate return( ber->ber_tag );
7120Sstevel@tonic-gate }
7130Sstevel@tonic-gate
7140Sstevel@tonic-gate Sockbuf *
7150Sstevel@tonic-gate LDAP_CALL
ber_sockbuf_alloc()7160Sstevel@tonic-gate ber_sockbuf_alloc()
7170Sstevel@tonic-gate {
7180Sstevel@tonic-gate return( (Sockbuf *)NSLBERI_CALLOC( 1, sizeof(struct sockbuf) ) );
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate
7210Sstevel@tonic-gate void
7220Sstevel@tonic-gate LDAP_CALL
ber_sockbuf_free(Sockbuf * p)7230Sstevel@tonic-gate ber_sockbuf_free(Sockbuf *p)
7240Sstevel@tonic-gate {
7250Sstevel@tonic-gate if ( p != NULL ) {
726*12023SDoug.Leavitt@Sun.COM #ifdef LDAP_SASLIO_HOOKS
727*12023SDoug.Leavitt@Sun.COM if ( p->sb_sasl_ctx != NULL)
728*12023SDoug.Leavitt@Sun.COM sasl_dispose(&p->sb_sasl_ctx);
729*12023SDoug.Leavitt@Sun.COM if ( p->sb_sasl_ibuf != NULL) {
730*12023SDoug.Leavitt@Sun.COM NSLBERI_FREE( p->sb_sasl_ibuf );
731*12023SDoug.Leavitt@Sun.COM }
732*12023SDoug.Leavitt@Sun.COM #endif
7330Sstevel@tonic-gate if ( p->sb_ber.ber_buf != NULL &&
7340Sstevel@tonic-gate !(p->sb_ber.ber_flags & LBER_FLAG_NO_FREE_BUFFER) ) {
7350Sstevel@tonic-gate NSLBERI_FREE( p->sb_ber.ber_buf );
7360Sstevel@tonic-gate }
7370Sstevel@tonic-gate NSLBERI_FREE(p);
7380Sstevel@tonic-gate }
7390Sstevel@tonic-gate }
7400Sstevel@tonic-gate
7410Sstevel@tonic-gate /*
7420Sstevel@tonic-gate * return 0 on success and -1 on error
7430Sstevel@tonic-gate */
7440Sstevel@tonic-gate int
7450Sstevel@tonic-gate LDAP_CALL
ber_set_option(struct berelement * ber,int option,void * value)7460Sstevel@tonic-gate ber_set_option( struct berelement *ber, int option, void *value )
7470Sstevel@tonic-gate {
7480Sstevel@tonic-gate
7490Sstevel@tonic-gate /*
7500Sstevel@tonic-gate * memory allocation callbacks are global, so it is OK to pass
7510Sstevel@tonic-gate * NULL for ber. Handle this as a special case.
7520Sstevel@tonic-gate */
7530Sstevel@tonic-gate if ( option == LBER_OPT_MEMALLOC_FN_PTRS ) {
7540Sstevel@tonic-gate /* struct copy */
7550Sstevel@tonic-gate nslberi_memalloc_fns = *((struct lber_memalloc_fns *)value);
7560Sstevel@tonic-gate return( 0 );
7570Sstevel@tonic-gate }
7580Sstevel@tonic-gate
7590Sstevel@tonic-gate /*
7600Sstevel@tonic-gate * lber_debug is global, so it is OK to pass
7610Sstevel@tonic-gate * NULL for ber. Handle this as a special case.
7620Sstevel@tonic-gate */
7630Sstevel@tonic-gate if ( option == LBER_OPT_DEBUG_LEVEL ) {
7640Sstevel@tonic-gate #ifdef LDAP_DEBUG
7650Sstevel@tonic-gate lber_debug = *(int *)value;
7660Sstevel@tonic-gate #endif
7670Sstevel@tonic-gate return( 0 );
7680Sstevel@tonic-gate }
7690Sstevel@tonic-gate
7700Sstevel@tonic-gate /*
7710Sstevel@tonic-gate * all the rest require a non-NULL ber
7720Sstevel@tonic-gate */
7730Sstevel@tonic-gate if ( !NSLBERI_VALID_BERELEMENT_POINTER( ber )) {
7740Sstevel@tonic-gate return( -1 );
7750Sstevel@tonic-gate }
7760Sstevel@tonic-gate
7770Sstevel@tonic-gate switch ( option ) {
7780Sstevel@tonic-gate case LBER_OPT_USE_DER:
7790Sstevel@tonic-gate case LBER_OPT_TRANSLATE_STRINGS:
7800Sstevel@tonic-gate if ( value != NULL ) {
7810Sstevel@tonic-gate ber->ber_options |= option;
7820Sstevel@tonic-gate } else {
7830Sstevel@tonic-gate ber->ber_options &= ~option;
7840Sstevel@tonic-gate }
7850Sstevel@tonic-gate break;
7860Sstevel@tonic-gate case LBER_OPT_REMAINING_BYTES:
7870Sstevel@tonic-gate ber->ber_end = ber->ber_ptr + *((ber_uint_t *)value);
7880Sstevel@tonic-gate break;
7890Sstevel@tonic-gate case LBER_OPT_TOTAL_BYTES:
7900Sstevel@tonic-gate ber->ber_end = ber->ber_buf + *((ber_uint_t *)value);
7910Sstevel@tonic-gate break;
7920Sstevel@tonic-gate case LBER_OPT_BYTES_TO_WRITE:
7930Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf + *((ber_uint_t *)value);
7940Sstevel@tonic-gate break;
7950Sstevel@tonic-gate default:
7960Sstevel@tonic-gate return( -1 );
7970Sstevel@tonic-gate }
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate return( 0 );
8000Sstevel@tonic-gate }
8010Sstevel@tonic-gate
8020Sstevel@tonic-gate /*
8030Sstevel@tonic-gate * return 0 on success and -1 on error
8040Sstevel@tonic-gate */
8050Sstevel@tonic-gate int
8060Sstevel@tonic-gate LDAP_CALL
ber_get_option(struct berelement * ber,int option,void * value)8070Sstevel@tonic-gate ber_get_option( struct berelement *ber, int option, void *value )
8080Sstevel@tonic-gate {
8090Sstevel@tonic-gate /*
8100Sstevel@tonic-gate * memory callocation callbacks are global, so it is OK to pass
8110Sstevel@tonic-gate * NULL for ber. Handle this as a special case
8120Sstevel@tonic-gate */
8130Sstevel@tonic-gate if ( option == LBER_OPT_MEMALLOC_FN_PTRS ) {
8140Sstevel@tonic-gate /* struct copy */
8150Sstevel@tonic-gate *((struct lber_memalloc_fns *)value) = nslberi_memalloc_fns;
8160Sstevel@tonic-gate return( 0 );
8170Sstevel@tonic-gate }
8180Sstevel@tonic-gate
8190Sstevel@tonic-gate /*
8200Sstevel@tonic-gate * lber_debug is global, so it is OK to pass
8210Sstevel@tonic-gate * NULL for ber. Handle this as a special case.
8220Sstevel@tonic-gate */
8230Sstevel@tonic-gate if ( option == LBER_OPT_DEBUG_LEVEL ) {
8240Sstevel@tonic-gate #ifdef LDAP_DEBUG
8250Sstevel@tonic-gate *(int *)value = lber_debug;
8260Sstevel@tonic-gate #endif
8270Sstevel@tonic-gate return( 0 );
8280Sstevel@tonic-gate }
8290Sstevel@tonic-gate /*
8300Sstevel@tonic-gate * all the rest require a non-NULL ber
8310Sstevel@tonic-gate */
8320Sstevel@tonic-gate if ( !NSLBERI_VALID_BERELEMENT_POINTER( ber )) {
8330Sstevel@tonic-gate return( -1 );
8340Sstevel@tonic-gate }
8350Sstevel@tonic-gate
8360Sstevel@tonic-gate switch ( option ) {
8370Sstevel@tonic-gate case LBER_OPT_USE_DER:
8380Sstevel@tonic-gate case LBER_OPT_TRANSLATE_STRINGS:
8390Sstevel@tonic-gate *((int *) value) = (ber->ber_options & option);
8400Sstevel@tonic-gate break;
8410Sstevel@tonic-gate case LBER_OPT_REMAINING_BYTES:
8420Sstevel@tonic-gate *((ber_uint_t *) value) = ber->ber_end - ber->ber_ptr;
8430Sstevel@tonic-gate break;
8440Sstevel@tonic-gate case LBER_OPT_TOTAL_BYTES:
8450Sstevel@tonic-gate *((ber_uint_t *) value) = ber->ber_end - ber->ber_buf;
8460Sstevel@tonic-gate break;
8470Sstevel@tonic-gate case LBER_OPT_BYTES_TO_WRITE:
8480Sstevel@tonic-gate *((ber_uint_t *) value) = ber->ber_ptr - ber->ber_buf;
8490Sstevel@tonic-gate break;
8500Sstevel@tonic-gate default:
8510Sstevel@tonic-gate return( -1 );
8520Sstevel@tonic-gate }
8530Sstevel@tonic-gate
8540Sstevel@tonic-gate return( 0 );
8550Sstevel@tonic-gate }
8560Sstevel@tonic-gate
8570Sstevel@tonic-gate /*
8580Sstevel@tonic-gate * return 0 on success and -1 on error
8590Sstevel@tonic-gate */
8600Sstevel@tonic-gate int
8610Sstevel@tonic-gate LDAP_CALL
ber_sockbuf_set_option(Sockbuf * sb,int option,void * value)8620Sstevel@tonic-gate ber_sockbuf_set_option( Sockbuf *sb, int option, void *value )
8630Sstevel@tonic-gate {
8640Sstevel@tonic-gate struct lber_x_ext_io_fns *extiofns;
8650Sstevel@tonic-gate
8660Sstevel@tonic-gate if ( !NSLBERI_VALID_SOCKBUF_POINTER( sb )) {
8670Sstevel@tonic-gate return( -1 );
8680Sstevel@tonic-gate }
8690Sstevel@tonic-gate
8700Sstevel@tonic-gate switch ( option ) {
8710Sstevel@tonic-gate case LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE:
8720Sstevel@tonic-gate sb->sb_max_incoming = *((ber_uint_t *) value);
8730Sstevel@tonic-gate /* FALL */
8740Sstevel@tonic-gate case LBER_SOCKBUF_OPT_TO_FILE:
8750Sstevel@tonic-gate case LBER_SOCKBUF_OPT_TO_FILE_ONLY:
8760Sstevel@tonic-gate case LBER_SOCKBUF_OPT_NO_READ_AHEAD:
8770Sstevel@tonic-gate if ( value != NULL ) {
8780Sstevel@tonic-gate sb->sb_options |= option;
8790Sstevel@tonic-gate } else {
8800Sstevel@tonic-gate sb->sb_options &= ~option;
8810Sstevel@tonic-gate }
8820Sstevel@tonic-gate break;
8830Sstevel@tonic-gate case LBER_SOCKBUF_OPT_DESC:
8840Sstevel@tonic-gate sb->sb_sd = *((LBER_SOCKET *) value);
8850Sstevel@tonic-gate break;
8860Sstevel@tonic-gate case LBER_SOCKBUF_OPT_COPYDESC:
8870Sstevel@tonic-gate sb->sb_copyfd = *((LBER_SOCKET *) value);
8880Sstevel@tonic-gate break;
8890Sstevel@tonic-gate case LBER_SOCKBUF_OPT_READ_FN:
8900Sstevel@tonic-gate sb->sb_io_fns.lbiof_read = (LDAP_IOF_READ_CALLBACK *) value;
8910Sstevel@tonic-gate nslberi_install_compat_io_fns( sb );
8920Sstevel@tonic-gate break;
8930Sstevel@tonic-gate case LBER_SOCKBUF_OPT_WRITE_FN:
8940Sstevel@tonic-gate sb->sb_io_fns.lbiof_write = (LDAP_IOF_WRITE_CALLBACK *) value;
8950Sstevel@tonic-gate nslberi_install_compat_io_fns( sb );
8960Sstevel@tonic-gate break;
8970Sstevel@tonic-gate case LBER_SOCKBUF_OPT_EXT_IO_FNS:
8980Sstevel@tonic-gate extiofns = (struct lber_x_ext_io_fns *) value;
8990Sstevel@tonic-gate if ( extiofns == NULL ) { /* remove */
9000Sstevel@tonic-gate (void)memset( (char *)&sb->sb_ext_io_fns, '\0',
9010Sstevel@tonic-gate sizeof(sb->sb_ext_io_fns ));
9020Sstevel@tonic-gate } else if ( extiofns->lbextiofn_size
9030Sstevel@tonic-gate == LBER_X_EXTIO_FNS_SIZE ) {
9040Sstevel@tonic-gate /* struct copy */
9050Sstevel@tonic-gate sb->sb_ext_io_fns = *extiofns;
9060Sstevel@tonic-gate } else {
9070Sstevel@tonic-gate return( -1 );
9080Sstevel@tonic-gate }
9090Sstevel@tonic-gate break;
9100Sstevel@tonic-gate default:
9110Sstevel@tonic-gate return( -1 );
9120Sstevel@tonic-gate }
9130Sstevel@tonic-gate
9140Sstevel@tonic-gate return( 0 );
9150Sstevel@tonic-gate }
9160Sstevel@tonic-gate
9170Sstevel@tonic-gate /*
9180Sstevel@tonic-gate * return 0 on success and -1 on error
9190Sstevel@tonic-gate */
9200Sstevel@tonic-gate int
9210Sstevel@tonic-gate LDAP_CALL
ber_sockbuf_get_option(Sockbuf * sb,int option,void * value)9220Sstevel@tonic-gate ber_sockbuf_get_option( Sockbuf *sb, int option, void *value )
9230Sstevel@tonic-gate {
9240Sstevel@tonic-gate struct lber_x_ext_io_fns *extiofns;
9250Sstevel@tonic-gate
9260Sstevel@tonic-gate if ( !NSLBERI_VALID_SOCKBUF_POINTER( sb )) {
9270Sstevel@tonic-gate return( -1 );
9280Sstevel@tonic-gate }
9290Sstevel@tonic-gate
9300Sstevel@tonic-gate switch ( option ) {
9310Sstevel@tonic-gate case LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE:
9320Sstevel@tonic-gate *((ber_uint_t *) value) = sb->sb_max_incoming;
9330Sstevel@tonic-gate break;
9340Sstevel@tonic-gate case LBER_SOCKBUF_OPT_TO_FILE:
9350Sstevel@tonic-gate case LBER_SOCKBUF_OPT_TO_FILE_ONLY:
9360Sstevel@tonic-gate case LBER_SOCKBUF_OPT_NO_READ_AHEAD:
9370Sstevel@tonic-gate *((int *) value) = (sb->sb_options & option);
9380Sstevel@tonic-gate break;
9390Sstevel@tonic-gate case LBER_SOCKBUF_OPT_DESC:
9400Sstevel@tonic-gate *((LBER_SOCKET *) value) = sb->sb_sd;
9410Sstevel@tonic-gate break;
9420Sstevel@tonic-gate case LBER_SOCKBUF_OPT_COPYDESC:
9430Sstevel@tonic-gate *((LBER_SOCKET *) value) = sb->sb_copyfd;
9440Sstevel@tonic-gate break;
9450Sstevel@tonic-gate case LBER_SOCKBUF_OPT_READ_FN:
9460Sstevel@tonic-gate *((LDAP_IOF_READ_CALLBACK **) value)
9470Sstevel@tonic-gate = sb->sb_io_fns.lbiof_read;
9480Sstevel@tonic-gate break;
9490Sstevel@tonic-gate case LBER_SOCKBUF_OPT_WRITE_FN:
9500Sstevel@tonic-gate *((LDAP_IOF_WRITE_CALLBACK **) value)
9510Sstevel@tonic-gate = sb->sb_io_fns.lbiof_write;
9520Sstevel@tonic-gate break;
9530Sstevel@tonic-gate case LBER_SOCKBUF_OPT_EXT_IO_FNS:
9540Sstevel@tonic-gate extiofns = (struct lber_x_ext_io_fns *) value;
9550Sstevel@tonic-gate if ( extiofns == NULL || extiofns->lbextiofn_size
9560Sstevel@tonic-gate != LBER_X_EXTIO_FNS_SIZE ) {
9570Sstevel@tonic-gate return( -1 );
9580Sstevel@tonic-gate }
9590Sstevel@tonic-gate /* struct copy */
9600Sstevel@tonic-gate *extiofns = sb->sb_ext_io_fns;
9610Sstevel@tonic-gate break;
9620Sstevel@tonic-gate default:
9630Sstevel@tonic-gate return( -1 );
9640Sstevel@tonic-gate }
9650Sstevel@tonic-gate
9660Sstevel@tonic-gate return( 0 );
9670Sstevel@tonic-gate }
9680Sstevel@tonic-gate
9690Sstevel@tonic-gate
9700Sstevel@tonic-gate /* new dboreham code below: */
9710Sstevel@tonic-gate
9720Sstevel@tonic-gate struct byte_buffer {
9730Sstevel@tonic-gate unsigned char *p;
9740Sstevel@tonic-gate int offset;
9750Sstevel@tonic-gate int length;
9760Sstevel@tonic-gate };
9770Sstevel@tonic-gate typedef struct byte_buffer byte_buffer;
9780Sstevel@tonic-gate
9790Sstevel@tonic-gate
9800Sstevel@tonic-gate /* This call allocates us a BerElement structure plus some extra memory.
9810Sstevel@tonic-gate * It returns a pointer to the BerElement, plus a pointer to the extra memory.
9820Sstevel@tonic-gate * This routine also allocates a ber data buffer within the same block, thus
9830Sstevel@tonic-gate * saving a call to calloc later when we read data.
9840Sstevel@tonic-gate */
9850Sstevel@tonic-gate void*
9860Sstevel@tonic-gate LDAP_CALL
ber_special_alloc(size_t size,BerElement ** ppBer)9870Sstevel@tonic-gate ber_special_alloc(size_t size, BerElement **ppBer)
9880Sstevel@tonic-gate {
9890Sstevel@tonic-gate char *mem = NULL;
9900Sstevel@tonic-gate
9910Sstevel@tonic-gate /* Make sure mem size requested is aligned */
9920Sstevel@tonic-gate if (0 != ( size & 0x03 )) {
9930Sstevel@tonic-gate size += (sizeof(ber_int_t) - (size & 0x03));
9940Sstevel@tonic-gate }
9950Sstevel@tonic-gate
9960Sstevel@tonic-gate mem = NSLBERI_MALLOC(sizeof(struct berelement) + EXBUFSIZ + size );
9970Sstevel@tonic-gate if (NULL == mem) {
9980Sstevel@tonic-gate return NULL;
9990Sstevel@tonic-gate }
10000Sstevel@tonic-gate *ppBer = (BerElement*) (mem + size);
10010Sstevel@tonic-gate memset(*ppBer,0,sizeof(struct berelement));
10020Sstevel@tonic-gate (*ppBer)->ber_tag = LBER_DEFAULT;
10030Sstevel@tonic-gate (*ppBer)->ber_buf = mem + size + sizeof(struct berelement);
10040Sstevel@tonic-gate (*ppBer)->ber_ptr = (*ppBer)->ber_buf;
10050Sstevel@tonic-gate (*ppBer)->ber_end = (*ppBer)->ber_buf + EXBUFSIZ;
10060Sstevel@tonic-gate (*ppBer)->ber_flags = LBER_FLAG_NO_FREE_BUFFER;
10070Sstevel@tonic-gate return (void*)mem;
10080Sstevel@tonic-gate }
10090Sstevel@tonic-gate
10100Sstevel@tonic-gate void
10110Sstevel@tonic-gate LDAP_CALL
ber_special_free(void * buf,BerElement * ber)10120Sstevel@tonic-gate ber_special_free(void* buf, BerElement *ber)
10130Sstevel@tonic-gate {
10140Sstevel@tonic-gate if (!(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER)) {
10150Sstevel@tonic-gate NSLBERI_FREE(ber->ber_buf);
10160Sstevel@tonic-gate }
10170Sstevel@tonic-gate NSLBERI_FREE( buf );
10180Sstevel@tonic-gate }
10190Sstevel@tonic-gate
10200Sstevel@tonic-gate static int
read_bytes(byte_buffer * b,unsigned char * return_buffer,int bytes_to_read)10210Sstevel@tonic-gate read_bytes(byte_buffer *b, unsigned char *return_buffer, int bytes_to_read)
10220Sstevel@tonic-gate {
10230Sstevel@tonic-gate /* copy up to bytes_to_read bytes into the caller's buffer, return the number of bytes copied */
10240Sstevel@tonic-gate int bytes_to_copy = 0;
10250Sstevel@tonic-gate
10260Sstevel@tonic-gate if (bytes_to_read <= (b->length - b->offset) ) {
10270Sstevel@tonic-gate bytes_to_copy = bytes_to_read;
10280Sstevel@tonic-gate } else {
10290Sstevel@tonic-gate bytes_to_copy = (b->length - b->offset);
10300Sstevel@tonic-gate }
10310Sstevel@tonic-gate if (1 == bytes_to_copy) {
10320Sstevel@tonic-gate *return_buffer = *(b->p+b->offset++);
10330Sstevel@tonic-gate } else
10340Sstevel@tonic-gate if (0 == bytes_to_copy) {
10350Sstevel@tonic-gate ;
10360Sstevel@tonic-gate } else
10370Sstevel@tonic-gate {
10380Sstevel@tonic-gate memcpy(return_buffer,b->p+b->offset,bytes_to_copy);
10390Sstevel@tonic-gate b->offset += bytes_to_copy;
10400Sstevel@tonic-gate }
10410Sstevel@tonic-gate return bytes_to_copy;
10420Sstevel@tonic-gate }
10430Sstevel@tonic-gate
10440Sstevel@tonic-gate /* return the tag - LBER_DEFAULT returned means trouble */
10450Sstevel@tonic-gate static ber_tag_t
get_buffer_tag(byte_buffer * sb)10460Sstevel@tonic-gate get_buffer_tag(byte_buffer *sb )
10470Sstevel@tonic-gate {
10480Sstevel@tonic-gate unsigned char xbyte;
10490Sstevel@tonic-gate ber_tag_t tag;
10500Sstevel@tonic-gate char *tagp;
10510Sstevel@tonic-gate int i;
10520Sstevel@tonic-gate
10530Sstevel@tonic-gate if ( (i = read_bytes( sb, &xbyte, 1 )) != 1 ) {
10540Sstevel@tonic-gate return( LBER_DEFAULT );
10550Sstevel@tonic-gate }
10560Sstevel@tonic-gate
10570Sstevel@tonic-gate if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) {
10580Sstevel@tonic-gate return( (ber_uint_t) xbyte );
10590Sstevel@tonic-gate }
10600Sstevel@tonic-gate
10610Sstevel@tonic-gate tagp = (char *) &tag;
10620Sstevel@tonic-gate tagp[0] = xbyte;
10630Sstevel@tonic-gate for ( i = 1; i < sizeof(ber_int_t); i++ ) {
10640Sstevel@tonic-gate if ( read_bytes( sb, &xbyte, 1 ) != 1 )
10650Sstevel@tonic-gate return( LBER_DEFAULT );
10660Sstevel@tonic-gate
10670Sstevel@tonic-gate tagp[i] = xbyte;
10680Sstevel@tonic-gate
10690Sstevel@tonic-gate if ( ! (xbyte & LBER_MORE_TAG_MASK) )
10700Sstevel@tonic-gate break;
10710Sstevel@tonic-gate }
10720Sstevel@tonic-gate
10730Sstevel@tonic-gate /* tag too big! */
10740Sstevel@tonic-gate if ( i == sizeof(ber_int_t) )
10750Sstevel@tonic-gate return( LBER_DEFAULT );
10760Sstevel@tonic-gate
10770Sstevel@tonic-gate /* want leading, not trailing 0's */
10780Sstevel@tonic-gate return( tag >> (sizeof(ber_int_t) - i - 1) );
10790Sstevel@tonic-gate }
10800Sstevel@tonic-gate
10810Sstevel@tonic-gate /* Like ber_get_next, but from a byte buffer the caller already has. */
10820Sstevel@tonic-gate /* Bytes_Scanned returns the number of bytes we actually looked at in the buffer. */
10830Sstevel@tonic-gate /* ber_get_next_buffer is now implemented in terms of ber_get_next_buffer_ext */
10840Sstevel@tonic-gate /* and is here for backward compatibility. This new function allows us to pass */
10850Sstevel@tonic-gate /* the Sockbuf structure along */
10860Sstevel@tonic-gate
10870Sstevel@tonic-gate ber_uint_t
10880Sstevel@tonic-gate LDAP_CALL
ber_get_next_buffer(void * buffer,size_t buffer_size,ber_len_t * len,BerElement * ber,ber_uint_t * Bytes_Scanned)10890Sstevel@tonic-gate ber_get_next_buffer( void *buffer, size_t buffer_size, ber_len_t *len,
10900Sstevel@tonic-gate BerElement *ber, ber_uint_t *Bytes_Scanned )
10910Sstevel@tonic-gate {
10920Sstevel@tonic-gate return (ber_get_next_buffer_ext( buffer, buffer_size, len, ber,
10930Sstevel@tonic-gate Bytes_Scanned, NULL));
10940Sstevel@tonic-gate }
10950Sstevel@tonic-gate
10960Sstevel@tonic-gate ber_uint_t
10970Sstevel@tonic-gate LDAP_CALL
ber_get_next_buffer_ext(void * buffer,size_t buffer_size,ber_len_t * len,BerElement * ber,ber_uint_t * Bytes_Scanned,Sockbuf * sock)10980Sstevel@tonic-gate ber_get_next_buffer_ext( void *buffer, size_t buffer_size, ber_len_t *len,
10990Sstevel@tonic-gate BerElement *ber, ber_uint_t *Bytes_Scanned, Sockbuf *sock )
11000Sstevel@tonic-gate {
11010Sstevel@tonic-gate ber_tag_t tag = 0;
11020Sstevel@tonic-gate ber_len_t netlen;
11030Sstevel@tonic-gate ber_uint_t toread;
11040Sstevel@tonic-gate unsigned char lc;
11050Sstevel@tonic-gate ssize_t rc;
11060Sstevel@tonic-gate int noctets, diff;
11070Sstevel@tonic-gate byte_buffer sb = {0};
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate
11100Sstevel@tonic-gate /*
11110Sstevel@tonic-gate * Any ber element looks like this: tag length contents.
11120Sstevel@tonic-gate * Assuming everything's ok, we return the tag byte (we
11130Sstevel@tonic-gate * can assume a single byte), return the length in len,
11140Sstevel@tonic-gate * and the rest of the undecoded element in buf.
11150Sstevel@tonic-gate *
11160Sstevel@tonic-gate * Assumptions:
11170Sstevel@tonic-gate * 1) small tags (less than 128)
11180Sstevel@tonic-gate * 2) definite lengths
11190Sstevel@tonic-gate * 3) primitive encodings used whenever possible
11200Sstevel@tonic-gate */
11210Sstevel@tonic-gate
11220Sstevel@tonic-gate /*
11230Sstevel@tonic-gate * first time through - malloc the buffer, set up ptrs, and
11240Sstevel@tonic-gate * read the tag and the length and as much of the rest as we can
11250Sstevel@tonic-gate */
11260Sstevel@tonic-gate
11270Sstevel@tonic-gate sb.p = buffer;
11280Sstevel@tonic-gate sb.length = buffer_size;
11290Sstevel@tonic-gate
11300Sstevel@tonic-gate if ( ber->ber_rwptr == NULL ) {
11310Sstevel@tonic-gate /*
11320Sstevel@tonic-gate * First, we read the tag.
11330Sstevel@tonic-gate */
11340Sstevel@tonic-gate
11350Sstevel@tonic-gate if ( (tag = get_buffer_tag( &sb )) == LBER_DEFAULT ) {
11360Sstevel@tonic-gate goto premature_exit;
11370Sstevel@tonic-gate }
11380Sstevel@tonic-gate ber->ber_tag = tag;
11390Sstevel@tonic-gate
11400Sstevel@tonic-gate /*
11410Sstevel@tonic-gate * Next, read the length. The first byte contains the length
11420Sstevel@tonic-gate * of the length. If bit 8 is set, the length is the long
11430Sstevel@tonic-gate * form, otherwise it's the short form. We don't allow a
11440Sstevel@tonic-gate * length that's greater than what we can hold in an unsigned
11450Sstevel@tonic-gate * long.
11460Sstevel@tonic-gate */
11470Sstevel@tonic-gate
11480Sstevel@tonic-gate *len = netlen = 0;
11490Sstevel@tonic-gate if ( read_bytes( &sb, &lc, 1 ) != 1 ) {
11500Sstevel@tonic-gate goto premature_exit;
11510Sstevel@tonic-gate }
11520Sstevel@tonic-gate if ( lc & 0x80 ) {
11530Sstevel@tonic-gate noctets = (lc & 0x7f);
11540Sstevel@tonic-gate if ( noctets > sizeof(ber_uint_t) )
11550Sstevel@tonic-gate goto premature_exit;
11560Sstevel@tonic-gate diff = sizeof(ber_uint_t) - noctets;
11570Sstevel@tonic-gate if ( read_bytes( &sb, (unsigned char *)&netlen + diff,
11580Sstevel@tonic-gate noctets ) != noctets ) {
11590Sstevel@tonic-gate goto premature_exit;
11600Sstevel@tonic-gate }
11610Sstevel@tonic-gate *len = LBER_NTOHL( netlen );
11620Sstevel@tonic-gate } else {
11630Sstevel@tonic-gate *len = lc;
11640Sstevel@tonic-gate }
11650Sstevel@tonic-gate ber->ber_len = *len;
11660Sstevel@tonic-gate
11670Sstevel@tonic-gate /*
11680Sstevel@tonic-gate * Finally, malloc a buffer for the contents and read it in.
11690Sstevel@tonic-gate * It's this buffer that's passed to all the other ber decoding
11700Sstevel@tonic-gate * routines.
11710Sstevel@tonic-gate */
11720Sstevel@tonic-gate
11730Sstevel@tonic-gate #if defined( DOS ) && !defined( _WIN32 )
11740Sstevel@tonic-gate if ( *len > 65535 ) { /* DOS can't allocate > 64K */
11750Sstevel@tonic-gate goto premature_exit;
11760Sstevel@tonic-gate }
11770Sstevel@tonic-gate #endif /* DOS && !_WIN32 */
11780Sstevel@tonic-gate
11790Sstevel@tonic-gate if ( (sock != NULL) &&
11800Sstevel@tonic-gate ( sock->sb_options & LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE )
11810Sstevel@tonic-gate && (*len > sock->sb_max_incoming) ) {
11820Sstevel@tonic-gate return( LBER_DEFAULT );
11830Sstevel@tonic-gate }
11840Sstevel@tonic-gate
11850Sstevel@tonic-gate if ( ber->ber_buf + *len > ber->ber_end ) {
11860Sstevel@tonic-gate if ( nslberi_ber_realloc( ber, *len ) != 0 )
11870Sstevel@tonic-gate goto premature_exit;
11880Sstevel@tonic-gate }
11890Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf;
11900Sstevel@tonic-gate ber->ber_end = ber->ber_buf + *len;
11910Sstevel@tonic-gate ber->ber_rwptr = ber->ber_buf;
11920Sstevel@tonic-gate }
11930Sstevel@tonic-gate
11940Sstevel@tonic-gate toread = (uintptr_t)ber->ber_end - (uintptr_t)ber->ber_rwptr;
11950Sstevel@tonic-gate do {
11960Sstevel@tonic-gate if ( (rc = read_bytes( &sb, (unsigned char *)ber->ber_rwptr,
11970Sstevel@tonic-gate (ber_int_t)toread )) <= 0 ) {
11980Sstevel@tonic-gate goto premature_exit;
11990Sstevel@tonic-gate }
12000Sstevel@tonic-gate
12010Sstevel@tonic-gate toread -= rc;
12020Sstevel@tonic-gate ber->ber_rwptr += rc;
12030Sstevel@tonic-gate } while ( toread > 0 );
12040Sstevel@tonic-gate
12050Sstevel@tonic-gate *len = ber->ber_len;
12060Sstevel@tonic-gate *Bytes_Scanned = sb.offset;
12070Sstevel@tonic-gate return( ber->ber_tag );
12080Sstevel@tonic-gate
12090Sstevel@tonic-gate premature_exit:
12100Sstevel@tonic-gate /*
12110Sstevel@tonic-gate * we're here because we hit the end of the buffer before seeing
12120Sstevel@tonic-gate * all of the PDU
12130Sstevel@tonic-gate */
12140Sstevel@tonic-gate *Bytes_Scanned = sb.offset;
12150Sstevel@tonic-gate return(LBER_DEFAULT);
12160Sstevel@tonic-gate }
12170Sstevel@tonic-gate
12180Sstevel@tonic-gate
12190Sstevel@tonic-gate /* The ber_flatten routine allocates a struct berval whose contents
12200Sstevel@tonic-gate * are a BER encoding taken from the ber argument. The bvPtr pointer
12210Sstevel@tonic-gate * points to the returned berval, which must be freed using
12220Sstevel@tonic-gate * ber_bvfree(). This routine returns 0 on success and -1 on error.
12230Sstevel@tonic-gate * The use of ber_flatten on a BerElement in which all '{' and '}'
12240Sstevel@tonic-gate * format modifiers have not been properly matched can result in a
12250Sstevel@tonic-gate * berval whose contents are not a valid BER encoding.
12260Sstevel@tonic-gate * Note that the ber_ptr is not modified.
12270Sstevel@tonic-gate */
12280Sstevel@tonic-gate int
12290Sstevel@tonic-gate LDAP_CALL
ber_flatten(BerElement * ber,struct berval ** bvPtr)12300Sstevel@tonic-gate ber_flatten( BerElement *ber, struct berval **bvPtr )
12310Sstevel@tonic-gate {
12320Sstevel@tonic-gate struct berval *new;
12330Sstevel@tonic-gate ber_len_t len;
12340Sstevel@tonic-gate
12350Sstevel@tonic-gate /* allocate a struct berval */
12360Sstevel@tonic-gate if ( (new = (struct berval *)NSLBERI_MALLOC( sizeof(struct berval) ))
12370Sstevel@tonic-gate == NULL ) {
12380Sstevel@tonic-gate return( -1 );
12390Sstevel@tonic-gate }
12400Sstevel@tonic-gate
12410Sstevel@tonic-gate /*
12420Sstevel@tonic-gate * Copy everything from the BerElement's ber_buf to ber_ptr
12430Sstevel@tonic-gate * into the berval structure.
12440Sstevel@tonic-gate */
12450Sstevel@tonic-gate if ( ber == NULL ) {
12460Sstevel@tonic-gate new->bv_val = NULL;
12470Sstevel@tonic-gate new->bv_len = 0;
12480Sstevel@tonic-gate } else {
12490Sstevel@tonic-gate len = ber->ber_ptr - ber->ber_buf;
12500Sstevel@tonic-gate if ( ( new->bv_val = (char *)NSLBERI_MALLOC( len + 1 )) == NULL ) {
12510Sstevel@tonic-gate ber_bvfree( new );
12520Sstevel@tonic-gate return( -1 );
12530Sstevel@tonic-gate }
12540Sstevel@tonic-gate SAFEMEMCPY( new->bv_val, ber->ber_buf, (size_t)len );
12550Sstevel@tonic-gate new->bv_val[len] = '\0';
12560Sstevel@tonic-gate new->bv_len = len;
12570Sstevel@tonic-gate }
12580Sstevel@tonic-gate
12590Sstevel@tonic-gate /* set bvPtr pointer to point to the returned berval */
12600Sstevel@tonic-gate *bvPtr = new;
12610Sstevel@tonic-gate
12620Sstevel@tonic-gate return( 0 );
12630Sstevel@tonic-gate }
12640Sstevel@tonic-gate
12650Sstevel@tonic-gate
12660Sstevel@tonic-gate /*
12670Sstevel@tonic-gate * The ber_init function constructs and returns a new BerElement
12680Sstevel@tonic-gate * containing a copy of the data in the bv argument. ber_init
12690Sstevel@tonic-gate * returns the null pointer on error.
12700Sstevel@tonic-gate */
12710Sstevel@tonic-gate BerElement *
12720Sstevel@tonic-gate LDAP_CALL
ber_init(const struct berval * bv)12730Sstevel@tonic-gate ber_init( const struct berval *bv )
12740Sstevel@tonic-gate {
12750Sstevel@tonic-gate BerElement *ber;
12760Sstevel@tonic-gate
12770Sstevel@tonic-gate /* construct BerElement */
12780Sstevel@tonic-gate if (( ber = ber_alloc_t( 0 )) != NULLBER ) {
12790Sstevel@tonic-gate /* copy data from the bv argument into BerElement */
12800Sstevel@tonic-gate /* XXXmcs: had to cast unsigned long bv_len to long */
12810Sstevel@tonic-gate if ( (ber_write ( ber, bv->bv_val, bv->bv_len, 0 ))
12820Sstevel@tonic-gate != (ber_slen_t)bv->bv_len ) {
12830Sstevel@tonic-gate ber_free( ber, 1 );
12840Sstevel@tonic-gate return( NULL );
12850Sstevel@tonic-gate }
12860Sstevel@tonic-gate }
12870Sstevel@tonic-gate
12880Sstevel@tonic-gate /*
12890Sstevel@tonic-gate * reset ber_ptr back to the beginning of buffer so that this new
12900Sstevel@tonic-gate * and initialized ber element can be READ
12910Sstevel@tonic-gate */
12920Sstevel@tonic-gate ber_reset( ber, 1);
12930Sstevel@tonic-gate
12940Sstevel@tonic-gate /*
12950Sstevel@tonic-gate * return a ptr to a new BerElement containing a copy of the data
12960Sstevel@tonic-gate * in the bv argument or a null pointer on error
12970Sstevel@tonic-gate */
12980Sstevel@tonic-gate return( ber );
12990Sstevel@tonic-gate }
13000Sstevel@tonic-gate
13010Sstevel@tonic-gate
13020Sstevel@tonic-gate /*
13030Sstevel@tonic-gate * memory allocation functions.
13040Sstevel@tonic-gate */
13050Sstevel@tonic-gate void *
nslberi_malloc(size_t size)13060Sstevel@tonic-gate nslberi_malloc( size_t size )
13070Sstevel@tonic-gate {
13080Sstevel@tonic-gate return( nslberi_memalloc_fns.lbermem_malloc == NULL ?
13090Sstevel@tonic-gate malloc( size ) :
13100Sstevel@tonic-gate nslberi_memalloc_fns.lbermem_malloc( size ));
13110Sstevel@tonic-gate }
13120Sstevel@tonic-gate
13130Sstevel@tonic-gate
13140Sstevel@tonic-gate void *
nslberi_calloc(size_t nelem,size_t elsize)13150Sstevel@tonic-gate nslberi_calloc( size_t nelem, size_t elsize )
13160Sstevel@tonic-gate {
13170Sstevel@tonic-gate return( nslberi_memalloc_fns.lbermem_calloc == NULL ?
13180Sstevel@tonic-gate calloc( nelem, elsize ) :
13190Sstevel@tonic-gate nslberi_memalloc_fns.lbermem_calloc( nelem, elsize ));
13200Sstevel@tonic-gate }
13210Sstevel@tonic-gate
13220Sstevel@tonic-gate
13230Sstevel@tonic-gate void *
nslberi_realloc(void * ptr,size_t size)13240Sstevel@tonic-gate nslberi_realloc( void *ptr, size_t size )
13250Sstevel@tonic-gate {
13260Sstevel@tonic-gate return( nslberi_memalloc_fns.lbermem_realloc == NULL ?
13270Sstevel@tonic-gate realloc( ptr, size ) :
13280Sstevel@tonic-gate nslberi_memalloc_fns.lbermem_realloc( ptr, size ));
13290Sstevel@tonic-gate }
13300Sstevel@tonic-gate
13310Sstevel@tonic-gate
13320Sstevel@tonic-gate void
nslberi_free(void * ptr)13330Sstevel@tonic-gate nslberi_free( void *ptr )
13340Sstevel@tonic-gate {
13350Sstevel@tonic-gate if ( nslberi_memalloc_fns.lbermem_free == NULL ) {
13360Sstevel@tonic-gate free( ptr );
13370Sstevel@tonic-gate } else {
13380Sstevel@tonic-gate nslberi_memalloc_fns.lbermem_free( ptr );
13390Sstevel@tonic-gate }
13400Sstevel@tonic-gate }
13410Sstevel@tonic-gate
13420Sstevel@tonic-gate
13430Sstevel@tonic-gate /*
13440Sstevel@tonic-gate ******************************************************************************
13450Sstevel@tonic-gate * functions to bridge the gap between new extended I/O functions that are
13460Sstevel@tonic-gate * installed using ber_sockbuf_set_option( ..., LBER_SOCKBUF_OPT_EXT_IO_FNS,
13470Sstevel@tonic-gate * ... ).
13480Sstevel@tonic-gate *
13490Sstevel@tonic-gate * the basic strategy is to use the new extended arg to hold a pointer to the
13500Sstevel@tonic-gate * Sockbuf itself so we can find the old functions and call them.
13510Sstevel@tonic-gate * note that the integer socket s passed in is not used. we use the sb_sd
13520Sstevel@tonic-gate * from the Sockbuf itself because it is the correct type.
13530Sstevel@tonic-gate */
13540Sstevel@tonic-gate static int
nslberi_extread_compat(int s,void * buf,int len,struct lextiof_socket_private * arg)13550Sstevel@tonic-gate nslberi_extread_compat( int s, void *buf, int len,
13560Sstevel@tonic-gate struct lextiof_socket_private *arg )
13570Sstevel@tonic-gate {
13580Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg;
13590Sstevel@tonic-gate
13600Sstevel@tonic-gate return( sb->sb_io_fns.lbiof_read( sb->sb_sd, buf, len ));
13610Sstevel@tonic-gate }
13620Sstevel@tonic-gate
13630Sstevel@tonic-gate
13640Sstevel@tonic-gate static int
nslberi_extwrite_compat(int s,const void * buf,int len,struct lextiof_socket_private * arg)13650Sstevel@tonic-gate nslberi_extwrite_compat( int s, const void *buf, int len,
13660Sstevel@tonic-gate struct lextiof_socket_private *arg )
13670Sstevel@tonic-gate {
13680Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg;
13690Sstevel@tonic-gate
13700Sstevel@tonic-gate return( sb->sb_io_fns.lbiof_write( sb->sb_sd, buf, len ));
13710Sstevel@tonic-gate }
13720Sstevel@tonic-gate
13730Sstevel@tonic-gate
13740Sstevel@tonic-gate /*
13750Sstevel@tonic-gate * Install I/O compatiblity functions. This can't fail.
13760Sstevel@tonic-gate */
13770Sstevel@tonic-gate static void
nslberi_install_compat_io_fns(Sockbuf * sb)13780Sstevel@tonic-gate nslberi_install_compat_io_fns( Sockbuf *sb )
13790Sstevel@tonic-gate {
13800Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE;
13810Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_read = nslberi_extread_compat;
13820Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_write = nslberi_extwrite_compat;
13830Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_socket_arg = (void *)sb;
13840Sstevel@tonic-gate }
13850Sstevel@tonic-gate /*
13860Sstevel@tonic-gate * end of compat I/O functions
13870Sstevel@tonic-gate ******************************************************************************
13880Sstevel@tonic-gate */
1389