1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate 7*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 8*0Sstevel@tonic-gate 9*0Sstevel@tonic-gate 10*0Sstevel@tonic-gate /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- 11*0Sstevel@tonic-gate * 12*0Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public License 13*0Sstevel@tonic-gate * Version 1.0 (the "NPL"); you may not use this file except in 14*0Sstevel@tonic-gate * compliance with the NPL. You may obtain a copy of the NPL at 15*0Sstevel@tonic-gate * http://www.mozilla.org/NPL/ 16*0Sstevel@tonic-gate * 17*0Sstevel@tonic-gate * Software distributed under the NPL is distributed on an "AS IS" basis, 18*0Sstevel@tonic-gate * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL 19*0Sstevel@tonic-gate * for the specific language governing rights and limitations under the 20*0Sstevel@tonic-gate * NPL. 21*0Sstevel@tonic-gate * 22*0Sstevel@tonic-gate * The Initial Developer of this code under the NPL is Netscape 23*0Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are 24*0Sstevel@tonic-gate * Copyright (C) 1998 Netscape Communications Corporation. All Rights 25*0Sstevel@tonic-gate * Reserved. 26*0Sstevel@tonic-gate */ 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gate /* 29*0Sstevel@tonic-gate * Copyright (c) 1990 Regents of the University of Michigan. 30*0Sstevel@tonic-gate * All rights reserved. 31*0Sstevel@tonic-gate * 32*0Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 33*0Sstevel@tonic-gate * provided that this notice is preserved and that due credit is given 34*0Sstevel@tonic-gate * to the University of Michigan at Ann Arbor. The name of the University 35*0Sstevel@tonic-gate * may not be used to endorse or promote products derived from this 36*0Sstevel@tonic-gate * software without specific prior written permission. This software 37*0Sstevel@tonic-gate * is provided ``as is'' without express or implied warranty. 38*0Sstevel@tonic-gate */ 39*0Sstevel@tonic-gate /* io.c - ber general i/o routines */ 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate #include "lber-int.h" 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate #define bergetc( sb, len ) ( sb->sb_ber.ber_end > sb->sb_ber.ber_ptr ? \ 44*0Sstevel@tonic-gate (unsigned char)*sb->sb_ber.ber_ptr++ : \ 45*0Sstevel@tonic-gate ber_filbuf( sb, len )) 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate # ifdef macintosh 48*0Sstevel@tonic-gate /* 49*0Sstevel@tonic-gate * MacTCP/OpenTransport 50*0Sstevel@tonic-gate */ 51*0Sstevel@tonic-gate # define read( s, b, l ) tcpread( s, 0, (unsigned char *)b, l, NULL ) 52*0Sstevel@tonic-gate # define MAX_WRITE 65535 53*0Sstevel@tonic-gate # define BerWrite( sb, b, l ) tcpwrite( sb->sb_sd, (unsigned char *)(b), (l<MAX_WRITE)? l : MAX_WRITE ) 54*0Sstevel@tonic-gate # else /* macintosh */ 55*0Sstevel@tonic-gate # if defined(_WIN32) || defined(_WINDOWS) || defined(XP_OS2) 56*0Sstevel@tonic-gate /* 57*0Sstevel@tonic-gate * 32-bit Windows Socket API (under Windows NT or Windows 95) 58*0Sstevel@tonic-gate */ 59*0Sstevel@tonic-gate # define read( s, b, l ) recv( s, b, l, 0 ) 60*0Sstevel@tonic-gate # define BerWrite( s, b, l ) send( s->sb_sd, b, l, 0 ) 61*0Sstevel@tonic-gate # else /* _WIN32 */ 62*0Sstevel@tonic-gate /* 63*0Sstevel@tonic-gate * everything else (Unix/BSD 4.3 socket API) 64*0Sstevel@tonic-gate */ 65*0Sstevel@tonic-gate # define BerWrite( sb, b, l ) write( sb->sb_sd, b, l ) 66*0Sstevel@tonic-gate # define udp_read( sb, b, l, al ) recvfrom(sb->sb_sd, (char *)b, l, 0, \ 67*0Sstevel@tonic-gate (struct sockaddr *)sb->sb_fromaddr, \ 68*0Sstevel@tonic-gate (al = sizeof(struct sockaddr), &al)) 69*0Sstevel@tonic-gate # define udp_write( sb, b, l ) sendto(sb->sb_sd, (char *)(b), l, 0, \ 70*0Sstevel@tonic-gate (struct sockaddr *)sb->sb_useaddr, sizeof(struct sockaddr)) 71*0Sstevel@tonic-gate # endif /* _WIN32 */ 72*0Sstevel@tonic-gate # endif /* macintosh */ 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate #ifndef udp_read 75*0Sstevel@tonic-gate #define udp_read( sb, b, l, al ) CLDAP NOT SUPPORTED 76*0Sstevel@tonic-gate #define udp_write( sb, b, l ) CLDAP NOT SUPPORTED 77*0Sstevel@tonic-gate #endif /* udp_read */ 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate #define EXBUFSIZ 1024 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate #ifdef LDAP_DEBUG 82*0Sstevel@tonic-gate int lber_debug; 83*0Sstevel@tonic-gate #endif 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate /* 86*0Sstevel@tonic-gate * function prototypes 87*0Sstevel@tonic-gate */ 88*0Sstevel@tonic-gate static void nslberi_install_compat_io_fns( Sockbuf *sb ); 89*0Sstevel@tonic-gate static int nslberi_extread_compat( int s, void *buf, int len, 90*0Sstevel@tonic-gate struct lextiof_socket_private *arg ); 91*0Sstevel@tonic-gate static int nslberi_extwrite_compat( int s, const void *buf, int len, 92*0Sstevel@tonic-gate struct lextiof_socket_private *arg ); 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate /* 96*0Sstevel@tonic-gate * internal global structure for memory allocation callback functions 97*0Sstevel@tonic-gate */ 98*0Sstevel@tonic-gate static struct lber_memalloc_fns nslberi_memalloc_fns; 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate /* 102*0Sstevel@tonic-gate * buffered read from "sb". 103*0Sstevel@tonic-gate * returns value of first character read on success and -1 on error. 104*0Sstevel@tonic-gate */ 105*0Sstevel@tonic-gate static int 106*0Sstevel@tonic-gate ber_filbuf( Sockbuf *sb, ber_slen_t len ) 107*0Sstevel@tonic-gate { 108*0Sstevel@tonic-gate ssize_t rc; 109*0Sstevel@tonic-gate #ifdef CLDAP 110*0Sstevel@tonic-gate int addrlen; 111*0Sstevel@tonic-gate #endif /* CLDAP */ 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate if ( sb->sb_ber.ber_buf == NULL ) { 114*0Sstevel@tonic-gate if ( (sb->sb_ber.ber_buf = (char *)NSLBERI_MALLOC( 115*0Sstevel@tonic-gate READBUFSIZ )) == NULL ) { 116*0Sstevel@tonic-gate return( -1 ); 117*0Sstevel@tonic-gate } 118*0Sstevel@tonic-gate sb->sb_ber.ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; 119*0Sstevel@tonic-gate sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf; 120*0Sstevel@tonic-gate sb->sb_ber.ber_end = sb->sb_ber.ber_buf; 121*0Sstevel@tonic-gate } 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate if ( sb->sb_naddr > 0 ) { 124*0Sstevel@tonic-gate #ifdef CLDAP 125*0Sstevel@tonic-gate rc = udp_read(sb, sb->sb_ber.ber_buf, READBUFSIZ, addrlen ); 126*0Sstevel@tonic-gate #ifdef LDAP_DEBUG 127*0Sstevel@tonic-gate if ( lber_debug ) { 128*0Sstevel@tonic-gate char msg[80]; 129*0Sstevel@tonic-gate sprintf( msg, "ber_filbuf udp_read %d bytes\n", 130*0Sstevel@tonic-gate rc ); 131*0Sstevel@tonic-gate ber_err_print( msg ); 132*0Sstevel@tonic-gate if ( lber_debug > 1 && rc > 0 ) 133*0Sstevel@tonic-gate lber_bprint( sb->sb_ber.ber_buf, rc ); 134*0Sstevel@tonic-gate } 135*0Sstevel@tonic-gate #endif /* LDAP_DEBUG */ 136*0Sstevel@tonic-gate #else /* CLDAP */ 137*0Sstevel@tonic-gate rc = -1; 138*0Sstevel@tonic-gate #endif /* CLDAP */ 139*0Sstevel@tonic-gate } else { 140*0Sstevel@tonic-gate if ( sb->sb_ext_io_fns.lbextiofn_read != NULL ) { 141*0Sstevel@tonic-gate rc = sb->sb_ext_io_fns.lbextiofn_read( 142*0Sstevel@tonic-gate sb->sb_sd, sb->sb_ber.ber_buf, 143*0Sstevel@tonic-gate ((sb->sb_options & LBER_SOCKBUF_OPT_NO_READ_AHEAD) 144*0Sstevel@tonic-gate && (len < READBUFSIZ)) ? len : READBUFSIZ, 145*0Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_socket_arg ); 146*0Sstevel@tonic-gate } else { 147*0Sstevel@tonic-gate rc = read( sb->sb_sd, sb->sb_ber.ber_buf, 148*0Sstevel@tonic-gate ((sb->sb_options & LBER_SOCKBUF_OPT_NO_READ_AHEAD) 149*0Sstevel@tonic-gate && (len < READBUFSIZ)) ? len : READBUFSIZ ); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate } 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate if ( rc > 0 ) { 154*0Sstevel@tonic-gate sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf + 1; 155*0Sstevel@tonic-gate sb->sb_ber.ber_end = sb->sb_ber.ber_buf + rc; 156*0Sstevel@tonic-gate return( (unsigned char)*sb->sb_ber.ber_buf ); 157*0Sstevel@tonic-gate } 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate return( -1 ); 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate static ber_int_t 164*0Sstevel@tonic-gate BerRead( Sockbuf *sb, char *buf, ber_slen_t len ) 165*0Sstevel@tonic-gate { 166*0Sstevel@tonic-gate int c; 167*0Sstevel@tonic-gate ber_int_t nread = 0; 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate while ( len > 0 ) { 170*0Sstevel@tonic-gate if ( (c = bergetc( sb, len )) < 0 ) { 171*0Sstevel@tonic-gate if ( nread > 0 ) 172*0Sstevel@tonic-gate break; 173*0Sstevel@tonic-gate return( c ); 174*0Sstevel@tonic-gate } 175*0Sstevel@tonic-gate *buf++ = c; 176*0Sstevel@tonic-gate nread++; 177*0Sstevel@tonic-gate len--; 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate return( nread ); 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate /* 185*0Sstevel@tonic-gate * Note: ber_read() only uses the ber_end and ber_ptr elements of ber. 186*0Sstevel@tonic-gate * Functions like ber_get_tag(), ber_skip_tag, and ber_peek_tag() rely on 187*0Sstevel@tonic-gate * that fact, so if this code is changed to use any additional elements of 188*0Sstevel@tonic-gate * the ber structure, those functions will need to be changed as well. 189*0Sstevel@tonic-gate */ 190*0Sstevel@tonic-gate ber_int_t 191*0Sstevel@tonic-gate LDAP_CALL 192*0Sstevel@tonic-gate ber_read( BerElement *ber, char *buf, ber_len_t len ) 193*0Sstevel@tonic-gate { 194*0Sstevel@tonic-gate ber_len_t actuallen; 195*0Sstevel@tonic-gate ber_uint_t nleft; 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate nleft = ber->ber_end - ber->ber_ptr; 198*0Sstevel@tonic-gate actuallen = nleft < len ? nleft : len; 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate SAFEMEMCPY( buf, ber->ber_ptr, (size_t)actuallen ); 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate ber->ber_ptr += actuallen; 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate return( (ber_int_t)actuallen ); 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate /* 208*0Sstevel@tonic-gate * enlarge the ber buffer. 209*0Sstevel@tonic-gate * return 0 on success, -1 on error. 210*0Sstevel@tonic-gate */ 211*0Sstevel@tonic-gate int 212*0Sstevel@tonic-gate nslberi_ber_realloc( BerElement *ber, ber_len_t len ) 213*0Sstevel@tonic-gate { 214*0Sstevel@tonic-gate ber_uint_t need, have, total; 215*0Sstevel@tonic-gate size_t have_bytes; 216*0Sstevel@tonic-gate Seqorset *s; 217*0Sstevel@tonic-gate ber_int_t off; 218*0Sstevel@tonic-gate char *oldbuf; 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate have_bytes = ber->ber_end - ber->ber_buf; 221*0Sstevel@tonic-gate have = have_bytes / EXBUFSIZ; 222*0Sstevel@tonic-gate need = (len < EXBUFSIZ ? 1 : (len + (EXBUFSIZ - 1)) / EXBUFSIZ); 223*0Sstevel@tonic-gate total = have * EXBUFSIZ + need * EXBUFSIZ; 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate oldbuf = ber->ber_buf; 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate if (ber->ber_buf == NULL) { 228*0Sstevel@tonic-gate if ( (ber->ber_buf = (char *)NSLBERI_MALLOC( (size_t)total )) 229*0Sstevel@tonic-gate == NULL ) { 230*0Sstevel@tonic-gate return( -1 ); 231*0Sstevel@tonic-gate } 232*0Sstevel@tonic-gate ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; 233*0Sstevel@tonic-gate } else { 234*0Sstevel@tonic-gate if ( ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER ) { 235*0Sstevel@tonic-gate /* transition to malloc'd buffer */ 236*0Sstevel@tonic-gate if ( (ber->ber_buf = (char *)NSLBERI_MALLOC( 237*0Sstevel@tonic-gate (size_t)total )) == NULL ) { 238*0Sstevel@tonic-gate return( -1 ); 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; 241*0Sstevel@tonic-gate /* copy existing data into new malloc'd buffer */ 242*0Sstevel@tonic-gate SAFEMEMCPY( ber->ber_buf, oldbuf, have_bytes ); 243*0Sstevel@tonic-gate } else { 244*0Sstevel@tonic-gate if ( (ber->ber_buf = (char *)NSLBERI_REALLOC( 245*0Sstevel@tonic-gate ber->ber_buf,(size_t)total )) == NULL ) { 246*0Sstevel@tonic-gate return( -1 ); 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate } 249*0Sstevel@tonic-gate } 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate ber->ber_end = ber->ber_buf + total; 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate /* 254*0Sstevel@tonic-gate * If the stinking thing was moved, we need to go through and 255*0Sstevel@tonic-gate * reset all the sos and ber pointers. Offsets would've been 256*0Sstevel@tonic-gate * a better idea... oh well. 257*0Sstevel@tonic-gate */ 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate if ( ber->ber_buf != oldbuf ) { 260*0Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf); 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate for ( s = ber->ber_sos; s != NULLSEQORSET; s = s->sos_next ) { 263*0Sstevel@tonic-gate off = s->sos_first - oldbuf; 264*0Sstevel@tonic-gate s->sos_first = ber->ber_buf + off; 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate off = s->sos_ptr - oldbuf; 267*0Sstevel@tonic-gate s->sos_ptr = ber->ber_buf + off; 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate return( 0 ); 272*0Sstevel@tonic-gate } 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate /* 275*0Sstevel@tonic-gate * returns "len" on success and -1 on failure. 276*0Sstevel@tonic-gate */ 277*0Sstevel@tonic-gate ber_int_t 278*0Sstevel@tonic-gate LDAP_CALL 279*0Sstevel@tonic-gate ber_write( BerElement *ber, char *buf, ber_len_t len, int nosos ) 280*0Sstevel@tonic-gate { 281*0Sstevel@tonic-gate if ( nosos || ber->ber_sos == NULL ) { 282*0Sstevel@tonic-gate if ( ber->ber_ptr + len > ber->ber_end ) { 283*0Sstevel@tonic-gate if ( nslberi_ber_realloc( ber, len ) != 0 ) 284*0Sstevel@tonic-gate return( -1 ); 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate SAFEMEMCPY( ber->ber_ptr, buf, (size_t)len ); 287*0Sstevel@tonic-gate ber->ber_ptr += len; 288*0Sstevel@tonic-gate return( len ); 289*0Sstevel@tonic-gate } else { 290*0Sstevel@tonic-gate if ( ber->ber_sos->sos_ptr + len > ber->ber_end ) { 291*0Sstevel@tonic-gate if ( nslberi_ber_realloc( ber, len ) != 0 ) 292*0Sstevel@tonic-gate return( -1 ); 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate SAFEMEMCPY( ber->ber_sos->sos_ptr, buf, (size_t)len ); 295*0Sstevel@tonic-gate ber->ber_sos->sos_ptr += len; 296*0Sstevel@tonic-gate ber->ber_sos->sos_clen += len; 297*0Sstevel@tonic-gate return( len ); 298*0Sstevel@tonic-gate } 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate void 302*0Sstevel@tonic-gate LDAP_CALL 303*0Sstevel@tonic-gate ber_free( BerElement *ber, int freebuf ) 304*0Sstevel@tonic-gate { 305*0Sstevel@tonic-gate if ( ber != NULL ) { 306*0Sstevel@tonic-gate if ( freebuf && 307*0Sstevel@tonic-gate !(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER)) { 308*0Sstevel@tonic-gate NSLBERI_FREE(ber->ber_buf); 309*0Sstevel@tonic-gate } 310*0Sstevel@tonic-gate NSLBERI_FREE( (char *) ber ); 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate /* 315*0Sstevel@tonic-gate * return >= 0 on success, -1 on failure. 316*0Sstevel@tonic-gate */ 317*0Sstevel@tonic-gate int 318*0Sstevel@tonic-gate LDAP_CALL 319*0Sstevel@tonic-gate ber_flush( Sockbuf *sb, BerElement *ber, int freeit ) 320*0Sstevel@tonic-gate { 321*0Sstevel@tonic-gate ssize_t nwritten, towrite, rc; 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate if ( ber->ber_rwptr == NULL ) { 324*0Sstevel@tonic-gate ber->ber_rwptr = ber->ber_buf; 325*0Sstevel@tonic-gate } else if (ber->ber_rwptr >= ber->ber_end) { 326*0Sstevel@tonic-gate /* we will use the ber_rwptr to continue an exited flush, 327*0Sstevel@tonic-gate so if rwptr is not within the buffer we return an error. */ 328*0Sstevel@tonic-gate return( -1 ); 329*0Sstevel@tonic-gate } 330*0Sstevel@tonic-gate towrite = ber->ber_ptr - ber->ber_rwptr; 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate #ifdef LDAP_DEBUG 333*0Sstevel@tonic-gate if ( lber_debug ) { 334*0Sstevel@tonic-gate char msg[80]; 335*0Sstevel@tonic-gate sprintf( msg, "ber_flush: %ld bytes to sd %ld%s\n", towrite, 336*0Sstevel@tonic-gate sb->sb_sd, ber->ber_rwptr != ber->ber_buf ? " (re-flush)" 337*0Sstevel@tonic-gate : "" ); 338*0Sstevel@tonic-gate ber_err_print( msg ); 339*0Sstevel@tonic-gate if ( lber_debug > 1 ) 340*0Sstevel@tonic-gate lber_bprint( ber->ber_rwptr, towrite ); 341*0Sstevel@tonic-gate } 342*0Sstevel@tonic-gate #endif 343*0Sstevel@tonic-gate #if !defined(macintosh) && !defined(DOS) 344*0Sstevel@tonic-gate if ( sb->sb_options & (LBER_SOCKBUF_OPT_TO_FILE | LBER_SOCKBUF_OPT_TO_FILE_ONLY) ) { 345*0Sstevel@tonic-gate rc = write( sb->sb_copyfd, ber->ber_buf, towrite ); 346*0Sstevel@tonic-gate if ( sb->sb_options & LBER_SOCKBUF_OPT_TO_FILE_ONLY ) { 347*0Sstevel@tonic-gate return( (int)rc ); 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate #endif 351*0Sstevel@tonic-gate 352*0Sstevel@tonic-gate nwritten = 0; 353*0Sstevel@tonic-gate do { 354*0Sstevel@tonic-gate if (sb->sb_naddr > 0) { 355*0Sstevel@tonic-gate #ifdef CLDAP 356*0Sstevel@tonic-gate rc = udp_write( sb, ber->ber_buf + nwritten, 357*0Sstevel@tonic-gate (size_t)towrite ); 358*0Sstevel@tonic-gate #else /* CLDAP */ 359*0Sstevel@tonic-gate rc = -1; 360*0Sstevel@tonic-gate #endif /* CLDAP */ 361*0Sstevel@tonic-gate if ( rc <= 0 ) 362*0Sstevel@tonic-gate return( -1 ); 363*0Sstevel@tonic-gate /* fake error if write was not atomic */ 364*0Sstevel@tonic-gate if (rc < towrite) { 365*0Sstevel@tonic-gate #if !defined( macintosh ) && !defined( DOS ) 366*0Sstevel@tonic-gate errno = EMSGSIZE; /* For Win32, see portable.h */ 367*0Sstevel@tonic-gate #endif 368*0Sstevel@tonic-gate return( -1 ); 369*0Sstevel@tonic-gate } 370*0Sstevel@tonic-gate } else { 371*0Sstevel@tonic-gate if ( sb->sb_ext_io_fns.lbextiofn_write != NULL ) { 372*0Sstevel@tonic-gate if ( (rc = sb->sb_ext_io_fns.lbextiofn_write( 373*0Sstevel@tonic-gate sb->sb_sd, ber->ber_rwptr, (size_t)towrite, 374*0Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_socket_arg )) 375*0Sstevel@tonic-gate <= 0 ) { 376*0Sstevel@tonic-gate return( -1 ); 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate } else { 379*0Sstevel@tonic-gate if ( (rc = BerWrite( sb, ber->ber_rwptr, 380*0Sstevel@tonic-gate (size_t) towrite )) <= 0 ) { 381*0Sstevel@tonic-gate return( -1 ); 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate } 384*0Sstevel@tonic-gate } 385*0Sstevel@tonic-gate towrite -= rc; 386*0Sstevel@tonic-gate nwritten += rc; 387*0Sstevel@tonic-gate ber->ber_rwptr += rc; 388*0Sstevel@tonic-gate } while ( towrite > 0 ); 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate if ( freeit ) 391*0Sstevel@tonic-gate ber_free( ber, 1 ); 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate return( 0 ); 394*0Sstevel@tonic-gate } 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate /* we pre-allocate a buffer to save the extra malloc later */ 398*0Sstevel@tonic-gate BerElement * 399*0Sstevel@tonic-gate LDAP_CALL 400*0Sstevel@tonic-gate ber_alloc_t( int options ) 401*0Sstevel@tonic-gate { 402*0Sstevel@tonic-gate BerElement *ber; 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate if ( (ber = (BerElement*)NSLBERI_CALLOC( 1, 405*0Sstevel@tonic-gate sizeof(struct berelement) + EXBUFSIZ )) == NULL ) { 406*0Sstevel@tonic-gate return( NULL ); 407*0Sstevel@tonic-gate } 408*0Sstevel@tonic-gate 409*0Sstevel@tonic-gate /* 410*0Sstevel@tonic-gate * for compatibility with the C LDAP API standard, we recognize 411*0Sstevel@tonic-gate * LBER_USE_DER as LBER_OPT_USE_DER. See lber.h for a bit more info. 412*0Sstevel@tonic-gate */ 413*0Sstevel@tonic-gate if ( options & LBER_USE_DER ) { 414*0Sstevel@tonic-gate options &= ~LBER_USE_DER; 415*0Sstevel@tonic-gate options |= LBER_OPT_USE_DER; 416*0Sstevel@tonic-gate } 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate ber->ber_tag = LBER_DEFAULT; 419*0Sstevel@tonic-gate ber->ber_options = options; 420*0Sstevel@tonic-gate ber->ber_buf = (char*)ber + sizeof(struct berelement); 421*0Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf; 422*0Sstevel@tonic-gate ber->ber_end = ber->ber_buf + EXBUFSIZ; 423*0Sstevel@tonic-gate ber->ber_flags = LBER_FLAG_NO_FREE_BUFFER; 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate return( ber ); 426*0Sstevel@tonic-gate } 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate 429*0Sstevel@tonic-gate BerElement * 430*0Sstevel@tonic-gate LDAP_CALL 431*0Sstevel@tonic-gate ber_alloc() 432*0Sstevel@tonic-gate { 433*0Sstevel@tonic-gate return( ber_alloc_t( 0 ) ); 434*0Sstevel@tonic-gate } 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate BerElement * 437*0Sstevel@tonic-gate LDAP_CALL 438*0Sstevel@tonic-gate der_alloc() 439*0Sstevel@tonic-gate { 440*0Sstevel@tonic-gate return( ber_alloc_t( LBER_OPT_USE_DER ) ); 441*0Sstevel@tonic-gate } 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate BerElement * 444*0Sstevel@tonic-gate LDAP_CALL 445*0Sstevel@tonic-gate ber_dup( BerElement *ber ) 446*0Sstevel@tonic-gate { 447*0Sstevel@tonic-gate BerElement *new; 448*0Sstevel@tonic-gate 449*0Sstevel@tonic-gate if ( (new = ber_alloc()) == NULL ) 450*0Sstevel@tonic-gate return( NULL ); 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate *new = *ber; 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate return( new ); 455*0Sstevel@tonic-gate } 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gate 458*0Sstevel@tonic-gate void 459*0Sstevel@tonic-gate LDAP_CALL 460*0Sstevel@tonic-gate ber_init_w_nullchar( BerElement *ber, int options ) 461*0Sstevel@tonic-gate { 462*0Sstevel@tonic-gate (void) memset( (char *)ber, '\0', sizeof(struct berelement) ); 463*0Sstevel@tonic-gate ber->ber_tag = LBER_DEFAULT; 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate /* 466*0Sstevel@tonic-gate * For compatibility with the C LDAP API standard, we recognize 467*0Sstevel@tonic-gate * LBER_USE_DER as LBER_OPT_USE_DER. See lber.h for a bit more info. 468*0Sstevel@tonic-gate */ 469*0Sstevel@tonic-gate if ( options & LBER_USE_DER ) { 470*0Sstevel@tonic-gate options &= ~LBER_USE_DER; 471*0Sstevel@tonic-gate options |= LBER_OPT_USE_DER; 472*0Sstevel@tonic-gate } 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate ber->ber_options = options; 475*0Sstevel@tonic-gate } 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate void 479*0Sstevel@tonic-gate LDAP_CALL 480*0Sstevel@tonic-gate ber_reset( BerElement *ber, int was_writing ) 481*0Sstevel@tonic-gate { 482*0Sstevel@tonic-gate if ( was_writing ) { 483*0Sstevel@tonic-gate ber->ber_end = ber->ber_ptr; 484*0Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf; 485*0Sstevel@tonic-gate } else { 486*0Sstevel@tonic-gate ber->ber_ptr = ber->ber_end; 487*0Sstevel@tonic-gate } 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate ber->ber_rwptr = NULL; 490*0Sstevel@tonic-gate } 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate #ifdef LDAP_DEBUG 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate void 496*0Sstevel@tonic-gate ber_dump( BerElement *ber, int inout ) 497*0Sstevel@tonic-gate { 498*0Sstevel@tonic-gate char msg[128]; 499*0Sstevel@tonic-gate sprintf( msg, "ber_dump: buf 0x%lx, ptr 0x%lx, rwptr 0x%lx, end 0x%lx\n", 500*0Sstevel@tonic-gate ber->ber_buf, ber->ber_ptr, ber->ber_rwptr, ber->ber_end ); 501*0Sstevel@tonic-gate ber_err_print( msg ); 502*0Sstevel@tonic-gate if ( inout == 1 ) { 503*0Sstevel@tonic-gate sprintf( msg, " current len %ld, contents:\n", 504*0Sstevel@tonic-gate ber->ber_end - ber->ber_ptr ); 505*0Sstevel@tonic-gate ber_err_print( msg ); 506*0Sstevel@tonic-gate lber_bprint( ber->ber_ptr, ber->ber_end - ber->ber_ptr ); 507*0Sstevel@tonic-gate } else { 508*0Sstevel@tonic-gate sprintf( msg, " current len %ld, contents:\n", 509*0Sstevel@tonic-gate ber->ber_ptr - ber->ber_buf ); 510*0Sstevel@tonic-gate ber_err_print( msg ); 511*0Sstevel@tonic-gate lber_bprint( ber->ber_buf, ber->ber_ptr - ber->ber_buf ); 512*0Sstevel@tonic-gate } 513*0Sstevel@tonic-gate } 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate void 516*0Sstevel@tonic-gate ber_sos_dump( Seqorset *sos ) 517*0Sstevel@tonic-gate { 518*0Sstevel@tonic-gate char msg[80]; 519*0Sstevel@tonic-gate ber_err_print ( "*** sos dump ***\n" ); 520*0Sstevel@tonic-gate while ( sos != NULLSEQORSET ) { 521*0Sstevel@tonic-gate sprintf( msg, "ber_sos_dump: clen %ld first 0x%lx ptr 0x%lx\n", 522*0Sstevel@tonic-gate sos->sos_clen, sos->sos_first, sos->sos_ptr ); 523*0Sstevel@tonic-gate ber_err_print( msg ); 524*0Sstevel@tonic-gate sprintf( msg, " current len %ld contents:\n", 525*0Sstevel@tonic-gate sos->sos_ptr - sos->sos_first ); 526*0Sstevel@tonic-gate ber_err_print( msg ); 527*0Sstevel@tonic-gate lber_bprint( sos->sos_first, sos->sos_ptr - sos->sos_first ); 528*0Sstevel@tonic-gate 529*0Sstevel@tonic-gate sos = sos->sos_next; 530*0Sstevel@tonic-gate } 531*0Sstevel@tonic-gate ber_err_print( "*** end dump ***\n" ); 532*0Sstevel@tonic-gate } 533*0Sstevel@tonic-gate 534*0Sstevel@tonic-gate #endif 535*0Sstevel@tonic-gate 536*0Sstevel@tonic-gate /* return the tag - LBER_DEFAULT returned means trouble */ 537*0Sstevel@tonic-gate static ber_tag_t 538*0Sstevel@tonic-gate get_tag( Sockbuf *sb ) 539*0Sstevel@tonic-gate { 540*0Sstevel@tonic-gate unsigned char xbyte; 541*0Sstevel@tonic-gate ber_tag_t tag; 542*0Sstevel@tonic-gate char *tagp; 543*0Sstevel@tonic-gate int i; 544*0Sstevel@tonic-gate 545*0Sstevel@tonic-gate if ( (i = BerRead( sb, (char *) &xbyte, 1 )) != 1 ) { 546*0Sstevel@tonic-gate return( LBER_DEFAULT ); 547*0Sstevel@tonic-gate } 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) { 550*0Sstevel@tonic-gate return( (ber_uint_t) xbyte ); 551*0Sstevel@tonic-gate } 552*0Sstevel@tonic-gate 553*0Sstevel@tonic-gate tagp = (char *) &tag; 554*0Sstevel@tonic-gate tagp[0] = xbyte; 555*0Sstevel@tonic-gate for ( i = 1; i < sizeof(ber_int_t); i++ ) { 556*0Sstevel@tonic-gate if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 ) 557*0Sstevel@tonic-gate return( LBER_DEFAULT ); 558*0Sstevel@tonic-gate 559*0Sstevel@tonic-gate tagp[i] = xbyte; 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate if ( ! (xbyte & LBER_MORE_TAG_MASK) ) 562*0Sstevel@tonic-gate break; 563*0Sstevel@tonic-gate } 564*0Sstevel@tonic-gate 565*0Sstevel@tonic-gate /* tag too big! */ 566*0Sstevel@tonic-gate if ( i == sizeof(ber_int_t) ) 567*0Sstevel@tonic-gate return( LBER_DEFAULT ); 568*0Sstevel@tonic-gate 569*0Sstevel@tonic-gate /* want leading, not trailing 0's */ 570*0Sstevel@tonic-gate return( tag >> (sizeof(ber_int_t) - i - 1) ); 571*0Sstevel@tonic-gate } 572*0Sstevel@tonic-gate 573*0Sstevel@tonic-gate ber_tag_t 574*0Sstevel@tonic-gate LDAP_CALL 575*0Sstevel@tonic-gate ber_get_next( Sockbuf *sb, ber_len_t *len, BerElement *ber ) 576*0Sstevel@tonic-gate { 577*0Sstevel@tonic-gate ber_tag_t tag = 0; 578*0Sstevel@tonic-gate ber_len_t netlen; 579*0Sstevel@tonic-gate ber_uint_t toread; 580*0Sstevel@tonic-gate unsigned char lc; 581*0Sstevel@tonic-gate ber_int_t rc; 582*0Sstevel@tonic-gate int noctets, diff; 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate #ifdef LDAP_DEBUG 585*0Sstevel@tonic-gate if ( lber_debug ) 586*0Sstevel@tonic-gate ber_err_print( "ber_get_next\n" ); 587*0Sstevel@tonic-gate #endif 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate /* 590*0Sstevel@tonic-gate * Any ber element looks like this: tag length contents. 591*0Sstevel@tonic-gate * Assuming everything's ok, we return the tag byte (we 592*0Sstevel@tonic-gate * can assume a single byte), return the length in len, 593*0Sstevel@tonic-gate * and the rest of the undecoded element in buf. 594*0Sstevel@tonic-gate * 595*0Sstevel@tonic-gate * Assumptions: 596*0Sstevel@tonic-gate * 1) small tags (less than 128) 597*0Sstevel@tonic-gate * 2) definite lengths 598*0Sstevel@tonic-gate * 3) primitive encodings used whenever possible 599*0Sstevel@tonic-gate */ 600*0Sstevel@tonic-gate 601*0Sstevel@tonic-gate /* 602*0Sstevel@tonic-gate * first time through - malloc the buffer, set up ptrs, and 603*0Sstevel@tonic-gate * read the tag and the length and as much of the rest as we can 604*0Sstevel@tonic-gate */ 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate if ( ber->ber_rwptr == NULL ) { 607*0Sstevel@tonic-gate /* 608*0Sstevel@tonic-gate * First, we read the tag. 609*0Sstevel@tonic-gate */ 610*0Sstevel@tonic-gate 611*0Sstevel@tonic-gate if ( (tag = get_tag( sb )) == LBER_DEFAULT ) { 612*0Sstevel@tonic-gate return( LBER_DEFAULT ); 613*0Sstevel@tonic-gate } 614*0Sstevel@tonic-gate ber->ber_tag = tag; 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate /* 617*0Sstevel@tonic-gate * Next, read the length. The first byte contains the length 618*0Sstevel@tonic-gate * of the length. If bit 8 is set, the length is the long 619*0Sstevel@tonic-gate * form, otherwise it's the short form. We don't allow a 620*0Sstevel@tonic-gate * length that's greater than what we can hold in an unsigned 621*0Sstevel@tonic-gate * long. 622*0Sstevel@tonic-gate */ 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate *len = netlen = 0; 625*0Sstevel@tonic-gate if ( BerRead( sb, (char *) &lc, 1 ) != 1 ) { 626*0Sstevel@tonic-gate return( LBER_DEFAULT ); 627*0Sstevel@tonic-gate } 628*0Sstevel@tonic-gate if ( lc & 0x80 ) { 629*0Sstevel@tonic-gate noctets = (lc & 0x7f); 630*0Sstevel@tonic-gate if ( noctets > sizeof(ber_uint_t) ) 631*0Sstevel@tonic-gate return( LBER_DEFAULT ); 632*0Sstevel@tonic-gate diff = sizeof(ber_uint_t) - noctets; 633*0Sstevel@tonic-gate if ( BerRead( sb, (char *) &netlen + diff, noctets ) != 634*0Sstevel@tonic-gate noctets ) { 635*0Sstevel@tonic-gate return( LBER_DEFAULT ); 636*0Sstevel@tonic-gate } 637*0Sstevel@tonic-gate *len = LBER_NTOHL( netlen ); 638*0Sstevel@tonic-gate } else { 639*0Sstevel@tonic-gate *len = lc; 640*0Sstevel@tonic-gate } 641*0Sstevel@tonic-gate ber->ber_len = *len; 642*0Sstevel@tonic-gate 643*0Sstevel@tonic-gate /* 644*0Sstevel@tonic-gate * Finally, malloc a buffer for the contents and read it in. 645*0Sstevel@tonic-gate * It's this buffer that's passed to all the other ber decoding 646*0Sstevel@tonic-gate * routines. 647*0Sstevel@tonic-gate */ 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate #if defined( DOS ) && !( defined( _WIN32 ) || defined(XP_OS2) ) 650*0Sstevel@tonic-gate if ( *len > 65535 ) { /* DOS can't allocate > 64K */ 651*0Sstevel@tonic-gate return( LBER_DEFAULT ); 652*0Sstevel@tonic-gate } 653*0Sstevel@tonic-gate #endif /* DOS && !_WIN32 */ 654*0Sstevel@tonic-gate 655*0Sstevel@tonic-gate if ( ( sb->sb_options & LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE ) 656*0Sstevel@tonic-gate && *len > sb->sb_max_incoming ) { 657*0Sstevel@tonic-gate return( LBER_DEFAULT ); 658*0Sstevel@tonic-gate } 659*0Sstevel@tonic-gate 660*0Sstevel@tonic-gate if ( (ber->ber_buf = (char *)NSLBERI_CALLOC( 1,(size_t)*len )) 661*0Sstevel@tonic-gate == NULL ) { 662*0Sstevel@tonic-gate return( LBER_DEFAULT ); 663*0Sstevel@tonic-gate } 664*0Sstevel@tonic-gate ber->ber_flags &= ~LBER_FLAG_NO_FREE_BUFFER; 665*0Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf; 666*0Sstevel@tonic-gate ber->ber_end = ber->ber_buf + *len; 667*0Sstevel@tonic-gate ber->ber_rwptr = ber->ber_buf; 668*0Sstevel@tonic-gate } 669*0Sstevel@tonic-gate 670*0Sstevel@tonic-gate toread = (uintptr_t)ber->ber_end - (uintptr_t)ber->ber_rwptr; 671*0Sstevel@tonic-gate do { 672*0Sstevel@tonic-gate if ( (rc = BerRead( sb, ber->ber_rwptr, (ber_int_t)toread )) <= 0 ) { 673*0Sstevel@tonic-gate return( LBER_DEFAULT ); 674*0Sstevel@tonic-gate } 675*0Sstevel@tonic-gate 676*0Sstevel@tonic-gate toread -= rc; 677*0Sstevel@tonic-gate ber->ber_rwptr += rc; 678*0Sstevel@tonic-gate } while ( toread > 0 ); 679*0Sstevel@tonic-gate 680*0Sstevel@tonic-gate #ifdef LDAP_DEBUG 681*0Sstevel@tonic-gate if ( lber_debug ) { 682*0Sstevel@tonic-gate char msg[80]; 683*0Sstevel@tonic-gate sprintf( msg, "ber_get_next: tag 0x%lx len %ld contents:\n", 684*0Sstevel@tonic-gate tag, ber->ber_len ); 685*0Sstevel@tonic-gate ber_err_print( msg ); 686*0Sstevel@tonic-gate if ( lber_debug > 1 ) 687*0Sstevel@tonic-gate ber_dump( ber, 1 ); 688*0Sstevel@tonic-gate } 689*0Sstevel@tonic-gate #endif 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gate *len = ber->ber_len; 692*0Sstevel@tonic-gate ber->ber_rwptr = NULL; 693*0Sstevel@tonic-gate return( ber->ber_tag ); 694*0Sstevel@tonic-gate } 695*0Sstevel@tonic-gate 696*0Sstevel@tonic-gate Sockbuf * 697*0Sstevel@tonic-gate LDAP_CALL 698*0Sstevel@tonic-gate ber_sockbuf_alloc() 699*0Sstevel@tonic-gate { 700*0Sstevel@tonic-gate return( (Sockbuf *)NSLBERI_CALLOC( 1, sizeof(struct sockbuf) ) ); 701*0Sstevel@tonic-gate } 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gate void 704*0Sstevel@tonic-gate LDAP_CALL 705*0Sstevel@tonic-gate ber_sockbuf_free(Sockbuf *p) 706*0Sstevel@tonic-gate { 707*0Sstevel@tonic-gate if ( p != NULL ) { 708*0Sstevel@tonic-gate if ( p->sb_ber.ber_buf != NULL && 709*0Sstevel@tonic-gate !(p->sb_ber.ber_flags & LBER_FLAG_NO_FREE_BUFFER) ) { 710*0Sstevel@tonic-gate NSLBERI_FREE( p->sb_ber.ber_buf ); 711*0Sstevel@tonic-gate } 712*0Sstevel@tonic-gate NSLBERI_FREE(p); 713*0Sstevel@tonic-gate } 714*0Sstevel@tonic-gate } 715*0Sstevel@tonic-gate 716*0Sstevel@tonic-gate /* 717*0Sstevel@tonic-gate * return 0 on success and -1 on error 718*0Sstevel@tonic-gate */ 719*0Sstevel@tonic-gate int 720*0Sstevel@tonic-gate LDAP_CALL 721*0Sstevel@tonic-gate ber_set_option( struct berelement *ber, int option, void *value ) 722*0Sstevel@tonic-gate { 723*0Sstevel@tonic-gate 724*0Sstevel@tonic-gate /* 725*0Sstevel@tonic-gate * memory allocation callbacks are global, so it is OK to pass 726*0Sstevel@tonic-gate * NULL for ber. Handle this as a special case. 727*0Sstevel@tonic-gate */ 728*0Sstevel@tonic-gate if ( option == LBER_OPT_MEMALLOC_FN_PTRS ) { 729*0Sstevel@tonic-gate /* struct copy */ 730*0Sstevel@tonic-gate nslberi_memalloc_fns = *((struct lber_memalloc_fns *)value); 731*0Sstevel@tonic-gate return( 0 ); 732*0Sstevel@tonic-gate } 733*0Sstevel@tonic-gate 734*0Sstevel@tonic-gate /* 735*0Sstevel@tonic-gate * lber_debug is global, so it is OK to pass 736*0Sstevel@tonic-gate * NULL for ber. Handle this as a special case. 737*0Sstevel@tonic-gate */ 738*0Sstevel@tonic-gate if ( option == LBER_OPT_DEBUG_LEVEL ) { 739*0Sstevel@tonic-gate #ifdef LDAP_DEBUG 740*0Sstevel@tonic-gate lber_debug = *(int *)value; 741*0Sstevel@tonic-gate #endif 742*0Sstevel@tonic-gate return( 0 ); 743*0Sstevel@tonic-gate } 744*0Sstevel@tonic-gate 745*0Sstevel@tonic-gate /* 746*0Sstevel@tonic-gate * all the rest require a non-NULL ber 747*0Sstevel@tonic-gate */ 748*0Sstevel@tonic-gate if ( !NSLBERI_VALID_BERELEMENT_POINTER( ber )) { 749*0Sstevel@tonic-gate return( -1 ); 750*0Sstevel@tonic-gate } 751*0Sstevel@tonic-gate 752*0Sstevel@tonic-gate switch ( option ) { 753*0Sstevel@tonic-gate case LBER_OPT_USE_DER: 754*0Sstevel@tonic-gate case LBER_OPT_TRANSLATE_STRINGS: 755*0Sstevel@tonic-gate if ( value != NULL ) { 756*0Sstevel@tonic-gate ber->ber_options |= option; 757*0Sstevel@tonic-gate } else { 758*0Sstevel@tonic-gate ber->ber_options &= ~option; 759*0Sstevel@tonic-gate } 760*0Sstevel@tonic-gate break; 761*0Sstevel@tonic-gate case LBER_OPT_REMAINING_BYTES: 762*0Sstevel@tonic-gate ber->ber_end = ber->ber_ptr + *((ber_uint_t *)value); 763*0Sstevel@tonic-gate break; 764*0Sstevel@tonic-gate case LBER_OPT_TOTAL_BYTES: 765*0Sstevel@tonic-gate ber->ber_end = ber->ber_buf + *((ber_uint_t *)value); 766*0Sstevel@tonic-gate break; 767*0Sstevel@tonic-gate case LBER_OPT_BYTES_TO_WRITE: 768*0Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf + *((ber_uint_t *)value); 769*0Sstevel@tonic-gate break; 770*0Sstevel@tonic-gate default: 771*0Sstevel@tonic-gate return( -1 ); 772*0Sstevel@tonic-gate } 773*0Sstevel@tonic-gate 774*0Sstevel@tonic-gate return( 0 ); 775*0Sstevel@tonic-gate } 776*0Sstevel@tonic-gate 777*0Sstevel@tonic-gate /* 778*0Sstevel@tonic-gate * return 0 on success and -1 on error 779*0Sstevel@tonic-gate */ 780*0Sstevel@tonic-gate int 781*0Sstevel@tonic-gate LDAP_CALL 782*0Sstevel@tonic-gate ber_get_option( struct berelement *ber, int option, void *value ) 783*0Sstevel@tonic-gate { 784*0Sstevel@tonic-gate /* 785*0Sstevel@tonic-gate * memory callocation callbacks are global, so it is OK to pass 786*0Sstevel@tonic-gate * NULL for ber. Handle this as a special case 787*0Sstevel@tonic-gate */ 788*0Sstevel@tonic-gate if ( option == LBER_OPT_MEMALLOC_FN_PTRS ) { 789*0Sstevel@tonic-gate /* struct copy */ 790*0Sstevel@tonic-gate *((struct lber_memalloc_fns *)value) = nslberi_memalloc_fns; 791*0Sstevel@tonic-gate return( 0 ); 792*0Sstevel@tonic-gate } 793*0Sstevel@tonic-gate 794*0Sstevel@tonic-gate /* 795*0Sstevel@tonic-gate * lber_debug is global, so it is OK to pass 796*0Sstevel@tonic-gate * NULL for ber. Handle this as a special case. 797*0Sstevel@tonic-gate */ 798*0Sstevel@tonic-gate if ( option == LBER_OPT_DEBUG_LEVEL ) { 799*0Sstevel@tonic-gate #ifdef LDAP_DEBUG 800*0Sstevel@tonic-gate *(int *)value = lber_debug; 801*0Sstevel@tonic-gate #endif 802*0Sstevel@tonic-gate return( 0 ); 803*0Sstevel@tonic-gate } 804*0Sstevel@tonic-gate /* 805*0Sstevel@tonic-gate * all the rest require a non-NULL ber 806*0Sstevel@tonic-gate */ 807*0Sstevel@tonic-gate if ( !NSLBERI_VALID_BERELEMENT_POINTER( ber )) { 808*0Sstevel@tonic-gate return( -1 ); 809*0Sstevel@tonic-gate } 810*0Sstevel@tonic-gate 811*0Sstevel@tonic-gate switch ( option ) { 812*0Sstevel@tonic-gate case LBER_OPT_USE_DER: 813*0Sstevel@tonic-gate case LBER_OPT_TRANSLATE_STRINGS: 814*0Sstevel@tonic-gate *((int *) value) = (ber->ber_options & option); 815*0Sstevel@tonic-gate break; 816*0Sstevel@tonic-gate case LBER_OPT_REMAINING_BYTES: 817*0Sstevel@tonic-gate *((ber_uint_t *) value) = ber->ber_end - ber->ber_ptr; 818*0Sstevel@tonic-gate break; 819*0Sstevel@tonic-gate case LBER_OPT_TOTAL_BYTES: 820*0Sstevel@tonic-gate *((ber_uint_t *) value) = ber->ber_end - ber->ber_buf; 821*0Sstevel@tonic-gate break; 822*0Sstevel@tonic-gate case LBER_OPT_BYTES_TO_WRITE: 823*0Sstevel@tonic-gate *((ber_uint_t *) value) = ber->ber_ptr - ber->ber_buf; 824*0Sstevel@tonic-gate break; 825*0Sstevel@tonic-gate default: 826*0Sstevel@tonic-gate return( -1 ); 827*0Sstevel@tonic-gate } 828*0Sstevel@tonic-gate 829*0Sstevel@tonic-gate return( 0 ); 830*0Sstevel@tonic-gate } 831*0Sstevel@tonic-gate 832*0Sstevel@tonic-gate /* 833*0Sstevel@tonic-gate * return 0 on success and -1 on error 834*0Sstevel@tonic-gate */ 835*0Sstevel@tonic-gate int 836*0Sstevel@tonic-gate LDAP_CALL 837*0Sstevel@tonic-gate ber_sockbuf_set_option( Sockbuf *sb, int option, void *value ) 838*0Sstevel@tonic-gate { 839*0Sstevel@tonic-gate struct lber_x_ext_io_fns *extiofns; 840*0Sstevel@tonic-gate 841*0Sstevel@tonic-gate if ( !NSLBERI_VALID_SOCKBUF_POINTER( sb )) { 842*0Sstevel@tonic-gate return( -1 ); 843*0Sstevel@tonic-gate } 844*0Sstevel@tonic-gate 845*0Sstevel@tonic-gate switch ( option ) { 846*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE: 847*0Sstevel@tonic-gate sb->sb_max_incoming = *((ber_uint_t *) value); 848*0Sstevel@tonic-gate /* FALL */ 849*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_TO_FILE: 850*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_TO_FILE_ONLY: 851*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_NO_READ_AHEAD: 852*0Sstevel@tonic-gate if ( value != NULL ) { 853*0Sstevel@tonic-gate sb->sb_options |= option; 854*0Sstevel@tonic-gate } else { 855*0Sstevel@tonic-gate sb->sb_options &= ~option; 856*0Sstevel@tonic-gate } 857*0Sstevel@tonic-gate break; 858*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_DESC: 859*0Sstevel@tonic-gate sb->sb_sd = *((LBER_SOCKET *) value); 860*0Sstevel@tonic-gate break; 861*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_COPYDESC: 862*0Sstevel@tonic-gate sb->sb_copyfd = *((LBER_SOCKET *) value); 863*0Sstevel@tonic-gate break; 864*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_READ_FN: 865*0Sstevel@tonic-gate sb->sb_io_fns.lbiof_read = (LDAP_IOF_READ_CALLBACK *) value; 866*0Sstevel@tonic-gate nslberi_install_compat_io_fns( sb ); 867*0Sstevel@tonic-gate break; 868*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_WRITE_FN: 869*0Sstevel@tonic-gate sb->sb_io_fns.lbiof_write = (LDAP_IOF_WRITE_CALLBACK *) value; 870*0Sstevel@tonic-gate nslberi_install_compat_io_fns( sb ); 871*0Sstevel@tonic-gate break; 872*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_EXT_IO_FNS: 873*0Sstevel@tonic-gate extiofns = (struct lber_x_ext_io_fns *) value; 874*0Sstevel@tonic-gate if ( extiofns == NULL ) { /* remove */ 875*0Sstevel@tonic-gate (void)memset( (char *)&sb->sb_ext_io_fns, '\0', 876*0Sstevel@tonic-gate sizeof(sb->sb_ext_io_fns )); 877*0Sstevel@tonic-gate } else if ( extiofns->lbextiofn_size 878*0Sstevel@tonic-gate == LBER_X_EXTIO_FNS_SIZE ) { 879*0Sstevel@tonic-gate /* struct copy */ 880*0Sstevel@tonic-gate sb->sb_ext_io_fns = *extiofns; 881*0Sstevel@tonic-gate } else { 882*0Sstevel@tonic-gate return( -1 ); 883*0Sstevel@tonic-gate } 884*0Sstevel@tonic-gate break; 885*0Sstevel@tonic-gate default: 886*0Sstevel@tonic-gate return( -1 ); 887*0Sstevel@tonic-gate } 888*0Sstevel@tonic-gate 889*0Sstevel@tonic-gate return( 0 ); 890*0Sstevel@tonic-gate } 891*0Sstevel@tonic-gate 892*0Sstevel@tonic-gate /* 893*0Sstevel@tonic-gate * return 0 on success and -1 on error 894*0Sstevel@tonic-gate */ 895*0Sstevel@tonic-gate int 896*0Sstevel@tonic-gate LDAP_CALL 897*0Sstevel@tonic-gate ber_sockbuf_get_option( Sockbuf *sb, int option, void *value ) 898*0Sstevel@tonic-gate { 899*0Sstevel@tonic-gate struct lber_x_ext_io_fns *extiofns; 900*0Sstevel@tonic-gate 901*0Sstevel@tonic-gate if ( !NSLBERI_VALID_SOCKBUF_POINTER( sb )) { 902*0Sstevel@tonic-gate return( -1 ); 903*0Sstevel@tonic-gate } 904*0Sstevel@tonic-gate 905*0Sstevel@tonic-gate switch ( option ) { 906*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE: 907*0Sstevel@tonic-gate *((ber_uint_t *) value) = sb->sb_max_incoming; 908*0Sstevel@tonic-gate break; 909*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_TO_FILE: 910*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_TO_FILE_ONLY: 911*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_NO_READ_AHEAD: 912*0Sstevel@tonic-gate *((int *) value) = (sb->sb_options & option); 913*0Sstevel@tonic-gate break; 914*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_DESC: 915*0Sstevel@tonic-gate *((LBER_SOCKET *) value) = sb->sb_sd; 916*0Sstevel@tonic-gate break; 917*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_COPYDESC: 918*0Sstevel@tonic-gate *((LBER_SOCKET *) value) = sb->sb_copyfd; 919*0Sstevel@tonic-gate break; 920*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_READ_FN: 921*0Sstevel@tonic-gate *((LDAP_IOF_READ_CALLBACK **) value) 922*0Sstevel@tonic-gate = sb->sb_io_fns.lbiof_read; 923*0Sstevel@tonic-gate break; 924*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_WRITE_FN: 925*0Sstevel@tonic-gate *((LDAP_IOF_WRITE_CALLBACK **) value) 926*0Sstevel@tonic-gate = sb->sb_io_fns.lbiof_write; 927*0Sstevel@tonic-gate break; 928*0Sstevel@tonic-gate case LBER_SOCKBUF_OPT_EXT_IO_FNS: 929*0Sstevel@tonic-gate extiofns = (struct lber_x_ext_io_fns *) value; 930*0Sstevel@tonic-gate if ( extiofns == NULL || extiofns->lbextiofn_size 931*0Sstevel@tonic-gate != LBER_X_EXTIO_FNS_SIZE ) { 932*0Sstevel@tonic-gate return( -1 ); 933*0Sstevel@tonic-gate } 934*0Sstevel@tonic-gate /* struct copy */ 935*0Sstevel@tonic-gate *extiofns = sb->sb_ext_io_fns; 936*0Sstevel@tonic-gate break; 937*0Sstevel@tonic-gate default: 938*0Sstevel@tonic-gate return( -1 ); 939*0Sstevel@tonic-gate } 940*0Sstevel@tonic-gate 941*0Sstevel@tonic-gate return( 0 ); 942*0Sstevel@tonic-gate } 943*0Sstevel@tonic-gate 944*0Sstevel@tonic-gate 945*0Sstevel@tonic-gate /* new dboreham code below: */ 946*0Sstevel@tonic-gate 947*0Sstevel@tonic-gate struct byte_buffer { 948*0Sstevel@tonic-gate unsigned char *p; 949*0Sstevel@tonic-gate int offset; 950*0Sstevel@tonic-gate int length; 951*0Sstevel@tonic-gate }; 952*0Sstevel@tonic-gate typedef struct byte_buffer byte_buffer; 953*0Sstevel@tonic-gate 954*0Sstevel@tonic-gate 955*0Sstevel@tonic-gate /* This call allocates us a BerElement structure plus some extra memory. 956*0Sstevel@tonic-gate * It returns a pointer to the BerElement, plus a pointer to the extra memory. 957*0Sstevel@tonic-gate * This routine also allocates a ber data buffer within the same block, thus 958*0Sstevel@tonic-gate * saving a call to calloc later when we read data. 959*0Sstevel@tonic-gate */ 960*0Sstevel@tonic-gate void* 961*0Sstevel@tonic-gate LDAP_CALL 962*0Sstevel@tonic-gate ber_special_alloc(size_t size, BerElement **ppBer) 963*0Sstevel@tonic-gate { 964*0Sstevel@tonic-gate char *mem = NULL; 965*0Sstevel@tonic-gate 966*0Sstevel@tonic-gate /* Make sure mem size requested is aligned */ 967*0Sstevel@tonic-gate if (0 != ( size & 0x03 )) { 968*0Sstevel@tonic-gate size += (sizeof(ber_int_t) - (size & 0x03)); 969*0Sstevel@tonic-gate } 970*0Sstevel@tonic-gate 971*0Sstevel@tonic-gate mem = NSLBERI_MALLOC(sizeof(struct berelement) + EXBUFSIZ + size ); 972*0Sstevel@tonic-gate if (NULL == mem) { 973*0Sstevel@tonic-gate return NULL; 974*0Sstevel@tonic-gate } 975*0Sstevel@tonic-gate *ppBer = (BerElement*) (mem + size); 976*0Sstevel@tonic-gate memset(*ppBer,0,sizeof(struct berelement)); 977*0Sstevel@tonic-gate (*ppBer)->ber_tag = LBER_DEFAULT; 978*0Sstevel@tonic-gate (*ppBer)->ber_buf = mem + size + sizeof(struct berelement); 979*0Sstevel@tonic-gate (*ppBer)->ber_ptr = (*ppBer)->ber_buf; 980*0Sstevel@tonic-gate (*ppBer)->ber_end = (*ppBer)->ber_buf + EXBUFSIZ; 981*0Sstevel@tonic-gate (*ppBer)->ber_flags = LBER_FLAG_NO_FREE_BUFFER; 982*0Sstevel@tonic-gate return (void*)mem; 983*0Sstevel@tonic-gate } 984*0Sstevel@tonic-gate 985*0Sstevel@tonic-gate void 986*0Sstevel@tonic-gate LDAP_CALL 987*0Sstevel@tonic-gate ber_special_free(void* buf, BerElement *ber) 988*0Sstevel@tonic-gate { 989*0Sstevel@tonic-gate if (!(ber->ber_flags & LBER_FLAG_NO_FREE_BUFFER)) { 990*0Sstevel@tonic-gate NSLBERI_FREE(ber->ber_buf); 991*0Sstevel@tonic-gate } 992*0Sstevel@tonic-gate NSLBERI_FREE( buf ); 993*0Sstevel@tonic-gate } 994*0Sstevel@tonic-gate 995*0Sstevel@tonic-gate static int 996*0Sstevel@tonic-gate read_bytes(byte_buffer *b, unsigned char *return_buffer, int bytes_to_read) 997*0Sstevel@tonic-gate { 998*0Sstevel@tonic-gate /* copy up to bytes_to_read bytes into the caller's buffer, return the number of bytes copied */ 999*0Sstevel@tonic-gate int bytes_to_copy = 0; 1000*0Sstevel@tonic-gate 1001*0Sstevel@tonic-gate if (bytes_to_read <= (b->length - b->offset) ) { 1002*0Sstevel@tonic-gate bytes_to_copy = bytes_to_read; 1003*0Sstevel@tonic-gate } else { 1004*0Sstevel@tonic-gate bytes_to_copy = (b->length - b->offset); 1005*0Sstevel@tonic-gate } 1006*0Sstevel@tonic-gate if (1 == bytes_to_copy) { 1007*0Sstevel@tonic-gate *return_buffer = *(b->p+b->offset++); 1008*0Sstevel@tonic-gate } else 1009*0Sstevel@tonic-gate if (0 == bytes_to_copy) { 1010*0Sstevel@tonic-gate ; 1011*0Sstevel@tonic-gate } else 1012*0Sstevel@tonic-gate { 1013*0Sstevel@tonic-gate memcpy(return_buffer,b->p+b->offset,bytes_to_copy); 1014*0Sstevel@tonic-gate b->offset += bytes_to_copy; 1015*0Sstevel@tonic-gate } 1016*0Sstevel@tonic-gate return bytes_to_copy; 1017*0Sstevel@tonic-gate } 1018*0Sstevel@tonic-gate 1019*0Sstevel@tonic-gate /* return the tag - LBER_DEFAULT returned means trouble */ 1020*0Sstevel@tonic-gate static ber_tag_t 1021*0Sstevel@tonic-gate get_buffer_tag(byte_buffer *sb ) 1022*0Sstevel@tonic-gate { 1023*0Sstevel@tonic-gate unsigned char xbyte; 1024*0Sstevel@tonic-gate ber_tag_t tag; 1025*0Sstevel@tonic-gate char *tagp; 1026*0Sstevel@tonic-gate int i; 1027*0Sstevel@tonic-gate 1028*0Sstevel@tonic-gate if ( (i = read_bytes( sb, &xbyte, 1 )) != 1 ) { 1029*0Sstevel@tonic-gate return( LBER_DEFAULT ); 1030*0Sstevel@tonic-gate } 1031*0Sstevel@tonic-gate 1032*0Sstevel@tonic-gate if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) { 1033*0Sstevel@tonic-gate return( (ber_uint_t) xbyte ); 1034*0Sstevel@tonic-gate } 1035*0Sstevel@tonic-gate 1036*0Sstevel@tonic-gate tagp = (char *) &tag; 1037*0Sstevel@tonic-gate tagp[0] = xbyte; 1038*0Sstevel@tonic-gate for ( i = 1; i < sizeof(ber_int_t); i++ ) { 1039*0Sstevel@tonic-gate if ( read_bytes( sb, &xbyte, 1 ) != 1 ) 1040*0Sstevel@tonic-gate return( LBER_DEFAULT ); 1041*0Sstevel@tonic-gate 1042*0Sstevel@tonic-gate tagp[i] = xbyte; 1043*0Sstevel@tonic-gate 1044*0Sstevel@tonic-gate if ( ! (xbyte & LBER_MORE_TAG_MASK) ) 1045*0Sstevel@tonic-gate break; 1046*0Sstevel@tonic-gate } 1047*0Sstevel@tonic-gate 1048*0Sstevel@tonic-gate /* tag too big! */ 1049*0Sstevel@tonic-gate if ( i == sizeof(ber_int_t) ) 1050*0Sstevel@tonic-gate return( LBER_DEFAULT ); 1051*0Sstevel@tonic-gate 1052*0Sstevel@tonic-gate /* want leading, not trailing 0's */ 1053*0Sstevel@tonic-gate return( tag >> (sizeof(ber_int_t) - i - 1) ); 1054*0Sstevel@tonic-gate } 1055*0Sstevel@tonic-gate 1056*0Sstevel@tonic-gate /* Like ber_get_next, but from a byte buffer the caller already has. */ 1057*0Sstevel@tonic-gate /* Bytes_Scanned returns the number of bytes we actually looked at in the buffer. */ 1058*0Sstevel@tonic-gate /* ber_get_next_buffer is now implemented in terms of ber_get_next_buffer_ext */ 1059*0Sstevel@tonic-gate /* and is here for backward compatibility. This new function allows us to pass */ 1060*0Sstevel@tonic-gate /* the Sockbuf structure along */ 1061*0Sstevel@tonic-gate 1062*0Sstevel@tonic-gate ber_uint_t 1063*0Sstevel@tonic-gate LDAP_CALL 1064*0Sstevel@tonic-gate ber_get_next_buffer( void *buffer, size_t buffer_size, ber_len_t *len, 1065*0Sstevel@tonic-gate BerElement *ber, ber_uint_t *Bytes_Scanned ) 1066*0Sstevel@tonic-gate { 1067*0Sstevel@tonic-gate return (ber_get_next_buffer_ext( buffer, buffer_size, len, ber, 1068*0Sstevel@tonic-gate Bytes_Scanned, NULL)); 1069*0Sstevel@tonic-gate } 1070*0Sstevel@tonic-gate 1071*0Sstevel@tonic-gate ber_uint_t 1072*0Sstevel@tonic-gate LDAP_CALL 1073*0Sstevel@tonic-gate ber_get_next_buffer_ext( void *buffer, size_t buffer_size, ber_len_t *len, 1074*0Sstevel@tonic-gate BerElement *ber, ber_uint_t *Bytes_Scanned, Sockbuf *sock ) 1075*0Sstevel@tonic-gate { 1076*0Sstevel@tonic-gate ber_tag_t tag = 0; 1077*0Sstevel@tonic-gate ber_len_t netlen; 1078*0Sstevel@tonic-gate ber_uint_t toread; 1079*0Sstevel@tonic-gate unsigned char lc; 1080*0Sstevel@tonic-gate ssize_t rc; 1081*0Sstevel@tonic-gate int noctets, diff; 1082*0Sstevel@tonic-gate byte_buffer sb = {0}; 1083*0Sstevel@tonic-gate 1084*0Sstevel@tonic-gate 1085*0Sstevel@tonic-gate /* 1086*0Sstevel@tonic-gate * Any ber element looks like this: tag length contents. 1087*0Sstevel@tonic-gate * Assuming everything's ok, we return the tag byte (we 1088*0Sstevel@tonic-gate * can assume a single byte), return the length in len, 1089*0Sstevel@tonic-gate * and the rest of the undecoded element in buf. 1090*0Sstevel@tonic-gate * 1091*0Sstevel@tonic-gate * Assumptions: 1092*0Sstevel@tonic-gate * 1) small tags (less than 128) 1093*0Sstevel@tonic-gate * 2) definite lengths 1094*0Sstevel@tonic-gate * 3) primitive encodings used whenever possible 1095*0Sstevel@tonic-gate */ 1096*0Sstevel@tonic-gate 1097*0Sstevel@tonic-gate /* 1098*0Sstevel@tonic-gate * first time through - malloc the buffer, set up ptrs, and 1099*0Sstevel@tonic-gate * read the tag and the length and as much of the rest as we can 1100*0Sstevel@tonic-gate */ 1101*0Sstevel@tonic-gate 1102*0Sstevel@tonic-gate sb.p = buffer; 1103*0Sstevel@tonic-gate sb.length = buffer_size; 1104*0Sstevel@tonic-gate 1105*0Sstevel@tonic-gate if ( ber->ber_rwptr == NULL ) { 1106*0Sstevel@tonic-gate /* 1107*0Sstevel@tonic-gate * First, we read the tag. 1108*0Sstevel@tonic-gate */ 1109*0Sstevel@tonic-gate 1110*0Sstevel@tonic-gate if ( (tag = get_buffer_tag( &sb )) == LBER_DEFAULT ) { 1111*0Sstevel@tonic-gate goto premature_exit; 1112*0Sstevel@tonic-gate } 1113*0Sstevel@tonic-gate ber->ber_tag = tag; 1114*0Sstevel@tonic-gate 1115*0Sstevel@tonic-gate /* 1116*0Sstevel@tonic-gate * Next, read the length. The first byte contains the length 1117*0Sstevel@tonic-gate * of the length. If bit 8 is set, the length is the long 1118*0Sstevel@tonic-gate * form, otherwise it's the short form. We don't allow a 1119*0Sstevel@tonic-gate * length that's greater than what we can hold in an unsigned 1120*0Sstevel@tonic-gate * long. 1121*0Sstevel@tonic-gate */ 1122*0Sstevel@tonic-gate 1123*0Sstevel@tonic-gate *len = netlen = 0; 1124*0Sstevel@tonic-gate if ( read_bytes( &sb, &lc, 1 ) != 1 ) { 1125*0Sstevel@tonic-gate goto premature_exit; 1126*0Sstevel@tonic-gate } 1127*0Sstevel@tonic-gate if ( lc & 0x80 ) { 1128*0Sstevel@tonic-gate noctets = (lc & 0x7f); 1129*0Sstevel@tonic-gate if ( noctets > sizeof(ber_uint_t) ) 1130*0Sstevel@tonic-gate goto premature_exit; 1131*0Sstevel@tonic-gate diff = sizeof(ber_uint_t) - noctets; 1132*0Sstevel@tonic-gate if ( read_bytes( &sb, (unsigned char *)&netlen + diff, 1133*0Sstevel@tonic-gate noctets ) != noctets ) { 1134*0Sstevel@tonic-gate goto premature_exit; 1135*0Sstevel@tonic-gate } 1136*0Sstevel@tonic-gate *len = LBER_NTOHL( netlen ); 1137*0Sstevel@tonic-gate } else { 1138*0Sstevel@tonic-gate *len = lc; 1139*0Sstevel@tonic-gate } 1140*0Sstevel@tonic-gate ber->ber_len = *len; 1141*0Sstevel@tonic-gate 1142*0Sstevel@tonic-gate /* 1143*0Sstevel@tonic-gate * Finally, malloc a buffer for the contents and read it in. 1144*0Sstevel@tonic-gate * It's this buffer that's passed to all the other ber decoding 1145*0Sstevel@tonic-gate * routines. 1146*0Sstevel@tonic-gate */ 1147*0Sstevel@tonic-gate 1148*0Sstevel@tonic-gate #if defined( DOS ) && !defined( _WIN32 ) 1149*0Sstevel@tonic-gate if ( *len > 65535 ) { /* DOS can't allocate > 64K */ 1150*0Sstevel@tonic-gate goto premature_exit; 1151*0Sstevel@tonic-gate } 1152*0Sstevel@tonic-gate #endif /* DOS && !_WIN32 */ 1153*0Sstevel@tonic-gate 1154*0Sstevel@tonic-gate if ( (sock != NULL) && 1155*0Sstevel@tonic-gate ( sock->sb_options & LBER_SOCKBUF_OPT_MAX_INCOMING_SIZE ) 1156*0Sstevel@tonic-gate && (*len > sock->sb_max_incoming) ) { 1157*0Sstevel@tonic-gate return( LBER_DEFAULT ); 1158*0Sstevel@tonic-gate } 1159*0Sstevel@tonic-gate 1160*0Sstevel@tonic-gate if ( ber->ber_buf + *len > ber->ber_end ) { 1161*0Sstevel@tonic-gate if ( nslberi_ber_realloc( ber, *len ) != 0 ) 1162*0Sstevel@tonic-gate goto premature_exit; 1163*0Sstevel@tonic-gate } 1164*0Sstevel@tonic-gate ber->ber_ptr = ber->ber_buf; 1165*0Sstevel@tonic-gate ber->ber_end = ber->ber_buf + *len; 1166*0Sstevel@tonic-gate ber->ber_rwptr = ber->ber_buf; 1167*0Sstevel@tonic-gate } 1168*0Sstevel@tonic-gate 1169*0Sstevel@tonic-gate toread = (uintptr_t)ber->ber_end - (uintptr_t)ber->ber_rwptr; 1170*0Sstevel@tonic-gate do { 1171*0Sstevel@tonic-gate if ( (rc = read_bytes( &sb, (unsigned char *)ber->ber_rwptr, 1172*0Sstevel@tonic-gate (ber_int_t)toread )) <= 0 ) { 1173*0Sstevel@tonic-gate goto premature_exit; 1174*0Sstevel@tonic-gate } 1175*0Sstevel@tonic-gate 1176*0Sstevel@tonic-gate toread -= rc; 1177*0Sstevel@tonic-gate ber->ber_rwptr += rc; 1178*0Sstevel@tonic-gate } while ( toread > 0 ); 1179*0Sstevel@tonic-gate 1180*0Sstevel@tonic-gate *len = ber->ber_len; 1181*0Sstevel@tonic-gate *Bytes_Scanned = sb.offset; 1182*0Sstevel@tonic-gate return( ber->ber_tag ); 1183*0Sstevel@tonic-gate 1184*0Sstevel@tonic-gate premature_exit: 1185*0Sstevel@tonic-gate /* 1186*0Sstevel@tonic-gate * we're here because we hit the end of the buffer before seeing 1187*0Sstevel@tonic-gate * all of the PDU 1188*0Sstevel@tonic-gate */ 1189*0Sstevel@tonic-gate *Bytes_Scanned = sb.offset; 1190*0Sstevel@tonic-gate return(LBER_DEFAULT); 1191*0Sstevel@tonic-gate } 1192*0Sstevel@tonic-gate 1193*0Sstevel@tonic-gate 1194*0Sstevel@tonic-gate /* The ber_flatten routine allocates a struct berval whose contents 1195*0Sstevel@tonic-gate * are a BER encoding taken from the ber argument. The bvPtr pointer 1196*0Sstevel@tonic-gate * points to the returned berval, which must be freed using 1197*0Sstevel@tonic-gate * ber_bvfree(). This routine returns 0 on success and -1 on error. 1198*0Sstevel@tonic-gate * The use of ber_flatten on a BerElement in which all '{' and '}' 1199*0Sstevel@tonic-gate * format modifiers have not been properly matched can result in a 1200*0Sstevel@tonic-gate * berval whose contents are not a valid BER encoding. 1201*0Sstevel@tonic-gate * Note that the ber_ptr is not modified. 1202*0Sstevel@tonic-gate */ 1203*0Sstevel@tonic-gate int 1204*0Sstevel@tonic-gate LDAP_CALL 1205*0Sstevel@tonic-gate ber_flatten( BerElement *ber, struct berval **bvPtr ) 1206*0Sstevel@tonic-gate { 1207*0Sstevel@tonic-gate struct berval *new; 1208*0Sstevel@tonic-gate ber_len_t len; 1209*0Sstevel@tonic-gate 1210*0Sstevel@tonic-gate /* allocate a struct berval */ 1211*0Sstevel@tonic-gate if ( (new = (struct berval *)NSLBERI_MALLOC( sizeof(struct berval) )) 1212*0Sstevel@tonic-gate == NULL ) { 1213*0Sstevel@tonic-gate return( -1 ); 1214*0Sstevel@tonic-gate } 1215*0Sstevel@tonic-gate 1216*0Sstevel@tonic-gate /* 1217*0Sstevel@tonic-gate * Copy everything from the BerElement's ber_buf to ber_ptr 1218*0Sstevel@tonic-gate * into the berval structure. 1219*0Sstevel@tonic-gate */ 1220*0Sstevel@tonic-gate if ( ber == NULL ) { 1221*0Sstevel@tonic-gate new->bv_val = NULL; 1222*0Sstevel@tonic-gate new->bv_len = 0; 1223*0Sstevel@tonic-gate } else { 1224*0Sstevel@tonic-gate len = ber->ber_ptr - ber->ber_buf; 1225*0Sstevel@tonic-gate if ( ( new->bv_val = (char *)NSLBERI_MALLOC( len + 1 )) == NULL ) { 1226*0Sstevel@tonic-gate ber_bvfree( new ); 1227*0Sstevel@tonic-gate return( -1 ); 1228*0Sstevel@tonic-gate } 1229*0Sstevel@tonic-gate SAFEMEMCPY( new->bv_val, ber->ber_buf, (size_t)len ); 1230*0Sstevel@tonic-gate new->bv_val[len] = '\0'; 1231*0Sstevel@tonic-gate new->bv_len = len; 1232*0Sstevel@tonic-gate } 1233*0Sstevel@tonic-gate 1234*0Sstevel@tonic-gate /* set bvPtr pointer to point to the returned berval */ 1235*0Sstevel@tonic-gate *bvPtr = new; 1236*0Sstevel@tonic-gate 1237*0Sstevel@tonic-gate return( 0 ); 1238*0Sstevel@tonic-gate } 1239*0Sstevel@tonic-gate 1240*0Sstevel@tonic-gate 1241*0Sstevel@tonic-gate /* 1242*0Sstevel@tonic-gate * The ber_init function constructs and returns a new BerElement 1243*0Sstevel@tonic-gate * containing a copy of the data in the bv argument. ber_init 1244*0Sstevel@tonic-gate * returns the null pointer on error. 1245*0Sstevel@tonic-gate */ 1246*0Sstevel@tonic-gate BerElement * 1247*0Sstevel@tonic-gate LDAP_CALL 1248*0Sstevel@tonic-gate ber_init( const struct berval *bv ) 1249*0Sstevel@tonic-gate { 1250*0Sstevel@tonic-gate BerElement *ber; 1251*0Sstevel@tonic-gate 1252*0Sstevel@tonic-gate /* construct BerElement */ 1253*0Sstevel@tonic-gate if (( ber = ber_alloc_t( 0 )) != NULLBER ) { 1254*0Sstevel@tonic-gate /* copy data from the bv argument into BerElement */ 1255*0Sstevel@tonic-gate /* XXXmcs: had to cast unsigned long bv_len to long */ 1256*0Sstevel@tonic-gate if ( (ber_write ( ber, bv->bv_val, bv->bv_len, 0 )) 1257*0Sstevel@tonic-gate != (ber_slen_t)bv->bv_len ) { 1258*0Sstevel@tonic-gate ber_free( ber, 1 ); 1259*0Sstevel@tonic-gate return( NULL ); 1260*0Sstevel@tonic-gate } 1261*0Sstevel@tonic-gate } 1262*0Sstevel@tonic-gate 1263*0Sstevel@tonic-gate /* 1264*0Sstevel@tonic-gate * reset ber_ptr back to the beginning of buffer so that this new 1265*0Sstevel@tonic-gate * and initialized ber element can be READ 1266*0Sstevel@tonic-gate */ 1267*0Sstevel@tonic-gate ber_reset( ber, 1); 1268*0Sstevel@tonic-gate 1269*0Sstevel@tonic-gate /* 1270*0Sstevel@tonic-gate * return a ptr to a new BerElement containing a copy of the data 1271*0Sstevel@tonic-gate * in the bv argument or a null pointer on error 1272*0Sstevel@tonic-gate */ 1273*0Sstevel@tonic-gate return( ber ); 1274*0Sstevel@tonic-gate } 1275*0Sstevel@tonic-gate 1276*0Sstevel@tonic-gate 1277*0Sstevel@tonic-gate /* 1278*0Sstevel@tonic-gate * memory allocation functions. 1279*0Sstevel@tonic-gate */ 1280*0Sstevel@tonic-gate void * 1281*0Sstevel@tonic-gate nslberi_malloc( size_t size ) 1282*0Sstevel@tonic-gate { 1283*0Sstevel@tonic-gate return( nslberi_memalloc_fns.lbermem_malloc == NULL ? 1284*0Sstevel@tonic-gate malloc( size ) : 1285*0Sstevel@tonic-gate nslberi_memalloc_fns.lbermem_malloc( size )); 1286*0Sstevel@tonic-gate } 1287*0Sstevel@tonic-gate 1288*0Sstevel@tonic-gate 1289*0Sstevel@tonic-gate void * 1290*0Sstevel@tonic-gate nslberi_calloc( size_t nelem, size_t elsize ) 1291*0Sstevel@tonic-gate { 1292*0Sstevel@tonic-gate return( nslberi_memalloc_fns.lbermem_calloc == NULL ? 1293*0Sstevel@tonic-gate calloc( nelem, elsize ) : 1294*0Sstevel@tonic-gate nslberi_memalloc_fns.lbermem_calloc( nelem, elsize )); 1295*0Sstevel@tonic-gate } 1296*0Sstevel@tonic-gate 1297*0Sstevel@tonic-gate 1298*0Sstevel@tonic-gate void * 1299*0Sstevel@tonic-gate nslberi_realloc( void *ptr, size_t size ) 1300*0Sstevel@tonic-gate { 1301*0Sstevel@tonic-gate return( nslberi_memalloc_fns.lbermem_realloc == NULL ? 1302*0Sstevel@tonic-gate realloc( ptr, size ) : 1303*0Sstevel@tonic-gate nslberi_memalloc_fns.lbermem_realloc( ptr, size )); 1304*0Sstevel@tonic-gate } 1305*0Sstevel@tonic-gate 1306*0Sstevel@tonic-gate 1307*0Sstevel@tonic-gate void 1308*0Sstevel@tonic-gate nslberi_free( void *ptr ) 1309*0Sstevel@tonic-gate { 1310*0Sstevel@tonic-gate if ( nslberi_memalloc_fns.lbermem_free == NULL ) { 1311*0Sstevel@tonic-gate free( ptr ); 1312*0Sstevel@tonic-gate } else { 1313*0Sstevel@tonic-gate nslberi_memalloc_fns.lbermem_free( ptr ); 1314*0Sstevel@tonic-gate } 1315*0Sstevel@tonic-gate } 1316*0Sstevel@tonic-gate 1317*0Sstevel@tonic-gate 1318*0Sstevel@tonic-gate /* 1319*0Sstevel@tonic-gate ****************************************************************************** 1320*0Sstevel@tonic-gate * functions to bridge the gap between new extended I/O functions that are 1321*0Sstevel@tonic-gate * installed using ber_sockbuf_set_option( ..., LBER_SOCKBUF_OPT_EXT_IO_FNS, 1322*0Sstevel@tonic-gate * ... ). 1323*0Sstevel@tonic-gate * 1324*0Sstevel@tonic-gate * the basic strategy is to use the new extended arg to hold a pointer to the 1325*0Sstevel@tonic-gate * Sockbuf itself so we can find the old functions and call them. 1326*0Sstevel@tonic-gate * note that the integer socket s passed in is not used. we use the sb_sd 1327*0Sstevel@tonic-gate * from the Sockbuf itself because it is the correct type. 1328*0Sstevel@tonic-gate */ 1329*0Sstevel@tonic-gate static int 1330*0Sstevel@tonic-gate nslberi_extread_compat( int s, void *buf, int len, 1331*0Sstevel@tonic-gate struct lextiof_socket_private *arg ) 1332*0Sstevel@tonic-gate { 1333*0Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg; 1334*0Sstevel@tonic-gate 1335*0Sstevel@tonic-gate return( sb->sb_io_fns.lbiof_read( sb->sb_sd, buf, len )); 1336*0Sstevel@tonic-gate } 1337*0Sstevel@tonic-gate 1338*0Sstevel@tonic-gate 1339*0Sstevel@tonic-gate static int 1340*0Sstevel@tonic-gate nslberi_extwrite_compat( int s, const void *buf, int len, 1341*0Sstevel@tonic-gate struct lextiof_socket_private *arg ) 1342*0Sstevel@tonic-gate { 1343*0Sstevel@tonic-gate Sockbuf *sb = (Sockbuf *)arg; 1344*0Sstevel@tonic-gate 1345*0Sstevel@tonic-gate return( sb->sb_io_fns.lbiof_write( sb->sb_sd, buf, len )); 1346*0Sstevel@tonic-gate } 1347*0Sstevel@tonic-gate 1348*0Sstevel@tonic-gate 1349*0Sstevel@tonic-gate /* 1350*0Sstevel@tonic-gate * Install I/O compatiblity functions. This can't fail. 1351*0Sstevel@tonic-gate */ 1352*0Sstevel@tonic-gate static void 1353*0Sstevel@tonic-gate nslberi_install_compat_io_fns( Sockbuf *sb ) 1354*0Sstevel@tonic-gate { 1355*0Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; 1356*0Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_read = nslberi_extread_compat; 1357*0Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_write = nslberi_extwrite_compat; 1358*0Sstevel@tonic-gate sb->sb_ext_io_fns.lbextiofn_socket_arg = (void *)sb; 1359*0Sstevel@tonic-gate } 1360*0Sstevel@tonic-gate /* 1361*0Sstevel@tonic-gate * end of compat I/O functions 1362*0Sstevel@tonic-gate ****************************************************************************** 1363*0Sstevel@tonic-gate */ 1364