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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 * 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 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 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 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 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