Back to index

openldap  2.4.31
sockbuf.c
Go to the documentation of this file.
00001 /* sockbuf.c - i/o routines with support for adding i/o layers. */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 
00017 #include "portable.h"
00018 
00019 #include <stdio.h>
00020 
00021 #include <ac/stdlib.h>
00022 
00023 #include <ac/ctype.h>
00024 #include <ac/errno.h>
00025 #include <ac/socket.h>
00026 #include <ac/string.h>
00027 #include <ac/unistd.h>
00028 
00029 #ifdef HAVE_IO_H
00030 #include <io.h>
00031 #endif /* HAVE_IO_H */
00032 
00033 #if defined( HAVE_FCNTL_H )
00034 #include <fcntl.h>
00035 #endif
00036 
00037 #if defined( HAVE_SYS_FILIO_H )
00038 #include <sys/filio.h>
00039 #elif defined( HAVE_SYS_IOCTL_H )
00040 #include <sys/ioctl.h>
00041 #endif
00042 
00043 #include "lber-int.h"
00044 
00045 #ifndef LBER_MIN_BUFF_SIZE
00046 #define LBER_MIN_BUFF_SIZE         4096
00047 #endif
00048 #ifndef LBER_MAX_BUFF_SIZE
00049 #define LBER_MAX_BUFF_SIZE         (65536*256)
00050 #endif
00051 #ifndef LBER_DEFAULT_READAHEAD
00052 #define LBER_DEFAULT_READAHEAD     16384
00053 #endif
00054 
00055 Sockbuf *
00056 ber_sockbuf_alloc( void )
00057 {
00058        Sockbuf                     *sb;
00059 
00060        sb = LBER_CALLOC( 1, sizeof( Sockbuf ) );
00061 
00062        if( sb == NULL ) return NULL;
00063 
00064        ber_int_sb_init( sb );
00065        return sb;
00066 }
00067 
00068 void
00069 ber_sockbuf_free( Sockbuf *sb )
00070 {
00071        assert( sb != NULL );
00072        assert( SOCKBUF_VALID( sb ) );
00073 
00074        ber_int_sb_close( sb );
00075        ber_int_sb_destroy( sb );
00076        LBER_FREE( sb );
00077 }
00078 
00079 /* Return values: -1: error, 0: no operation performed or the answer is false,
00080  * 1: successful operation or the answer is true
00081  */
00082 int
00083 ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
00084 {
00085        Sockbuf_IO_Desc             *p;
00086        int                  ret = 0;
00087 
00088        assert( sb != NULL );
00089        assert( SOCKBUF_VALID( sb ) );
00090 
00091        switch ( opt ) {
00092               case LBER_SB_OPT_HAS_IO:
00093                      p = sb->sb_iod;
00094                      while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) {
00095                             p = p->sbiod_next;
00096                      }
00097    
00098                      if ( p ) {
00099                             ret = 1;
00100                      }
00101                      break;
00102 
00103               case LBER_SB_OPT_GET_FD:
00104                      if ( arg != NULL ) {
00105                             *((ber_socket_t *)arg) = sb->sb_fd;
00106                      }
00107                      ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1);
00108                      break;
00109 
00110               case LBER_SB_OPT_SET_FD:
00111                      sb->sb_fd = *((ber_socket_t *)arg);
00112                      ret = 1;
00113                      break;
00114 
00115               case LBER_SB_OPT_SET_NONBLOCK:
00116                      ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL)
00117                             ? -1 : 1;
00118                      break;
00119 
00120               case LBER_SB_OPT_DRAIN: {
00121                             /* Drain the data source to enable possible errors (e.g.
00122                              * TLS) to be propagated to the upper layers
00123                              */
00124                             char buf[LBER_MIN_BUFF_SIZE];
00125 
00126                             do {
00127                                    ret = ber_int_sb_read( sb, buf, sizeof( buf ) );
00128                             } while ( ret == sizeof( buf ) );
00129 
00130                             ret = 1;
00131                      } break;
00132 
00133               case LBER_SB_OPT_NEEDS_READ:
00134                      ret = ( sb->sb_trans_needs_read ? 1 : 0 );
00135                      break;
00136 
00137               case LBER_SB_OPT_NEEDS_WRITE:
00138                      ret = ( sb->sb_trans_needs_write ? 1 : 0 );
00139                      break;
00140 
00141               case LBER_SB_OPT_GET_MAX_INCOMING:
00142                      if ( arg != NULL ) {
00143                             *((ber_len_t *)arg) = sb->sb_max_incoming;
00144                      }
00145                      ret = 1;
00146                      break;
00147 
00148               case LBER_SB_OPT_SET_MAX_INCOMING:
00149                      sb->sb_max_incoming = *((ber_len_t *)arg);
00150                      ret = 1;
00151                      break;
00152 
00153               case LBER_SB_OPT_UNGET_BUF:
00154 #ifdef LDAP_PF_LOCAL_SENDMSG
00155                      sb->sb_ungetlen = ((struct berval *)arg)->bv_len;
00156                      if ( sb->sb_ungetlen <= sizeof( sb->sb_ungetbuf )) {
00157                             AC_MEMCPY( sb->sb_ungetbuf, ((struct berval *)arg)->bv_val,
00158                                    sb->sb_ungetlen );
00159                             ret = 1;
00160                      } else {
00161                             sb->sb_ungetlen = 0;
00162                             ret = -1;
00163                      }
00164 #endif
00165                      break;
00166 
00167               default:
00168                      ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, opt, arg );
00169                      break;
00170    }
00171 
00172        return ret;
00173 }
00174 
00175 int
00176 ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )
00177 {
00178        Sockbuf_IO_Desc             *d, *p, **q;
00179    
00180        assert( sb != NULL );
00181        assert( SOCKBUF_VALID( sb ) );
00182    
00183        if ( sbio == NULL ) {
00184               return -1;
00185        }
00186    
00187        q = &sb->sb_iod;
00188        p = *q;
00189        while ( p && p->sbiod_level > layer ) {
00190               q = &p->sbiod_next;
00191               p = *q;
00192        }
00193    
00194        d = LBER_MALLOC( sizeof( *d ) );
00195        if ( d == NULL ) {
00196               return -1;
00197        }
00198    
00199        d->sbiod_level = layer;
00200        d->sbiod_sb = sb;
00201        d->sbiod_io = sbio;
00202        memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) );
00203        d->sbiod_next = p;
00204        *q = d;
00205 
00206        if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) ) {
00207               return -1;
00208        }
00209 
00210        return 0;
00211 }
00212    
00213 int
00214 ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer )
00215 {
00216        Sockbuf_IO_Desc             *p, **q;
00217 
00218        assert( sb != NULL );
00219        assert( SOCKBUF_VALID( sb ) );
00220    
00221        if ( sb->sb_iod == NULL ) {
00222               return -1;
00223        }
00224    
00225        q = &sb->sb_iod;
00226        while ( *q != NULL ) {
00227               p = *q;
00228               if ( layer == p->sbiod_level && p->sbiod_io == sbio ) {
00229                      if ( p->sbiod_io->sbi_remove != NULL &&
00230                             p->sbiod_io->sbi_remove( p ) < 0 )
00231                      {
00232                             return -1;
00233                      }
00234                      *q = p->sbiod_next;
00235                      LBER_FREE( p );
00236                      break;
00237               }
00238               q = &p->sbiod_next;
00239        }
00240 
00241        return 0;
00242 }
00243 
00244 void
00245 ber_pvt_sb_buf_init( Sockbuf_Buf *buf )
00246 {
00247        buf->buf_base = NULL;
00248        buf->buf_ptr = 0;
00249        buf->buf_end = 0;
00250        buf->buf_size = 0;
00251 }
00252 
00253 void
00254 ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf )
00255 {
00256        assert( buf != NULL);
00257 
00258        if (buf->buf_base) {
00259               LBER_FREE( buf->buf_base );
00260        }
00261        ber_pvt_sb_buf_init( buf );
00262 }
00263 
00264 int
00265 ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize )
00266 {
00267        ber_len_t            pw;
00268        char                 *p;
00269    
00270        assert( buf != NULL );
00271 
00272        for ( pw = LBER_MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) {
00273               if (pw > LBER_MAX_BUFF_SIZE) return -1;
00274        }
00275 
00276        if ( buf->buf_size < pw ) {
00277               p = LBER_REALLOC( buf->buf_base, pw );
00278               if ( p == NULL ) return -1;
00279               buf->buf_base = p;
00280               buf->buf_size = pw;
00281        }
00282        return 0;
00283 }
00284 
00285 ber_len_t
00286 ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
00287 {
00288        ber_len_t            max;
00289 
00290        assert( buf != NULL );
00291        assert( sbb != NULL );
00292 #if 0
00293        assert( sbb->buf_size > 0 );
00294 #endif
00295 
00296        max = sbb->buf_end - sbb->buf_ptr;
00297        max = ( max < len) ? max : len;
00298        if ( max ) {
00299               AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max );
00300               sbb->buf_ptr += max;
00301               if ( sbb->buf_ptr >= sbb->buf_end ) {
00302                      sbb->buf_ptr = sbb->buf_end = 0;
00303               }
00304    }
00305        return max;
00306 }
00307 
00308 ber_slen_t
00309 ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
00310 {
00311        ber_len_t            to_go;
00312        ber_slen_t ret;
00313 
00314        assert( sbiod != NULL );
00315        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
00316 
00317        to_go = buf_out->buf_end - buf_out->buf_ptr;
00318        assert( to_go > 0 );
00319    
00320        for(;;) {
00321               ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base +
00322                      buf_out->buf_ptr, to_go );
00323 #ifdef EINTR
00324               if ((ret<0) && (errno==EINTR)) continue;
00325 #endif
00326               break;
00327        }
00328 
00329        if ( ret <= 0 ) return ret;
00330    
00331        buf_out->buf_ptr += ret;
00332        if (buf_out->buf_ptr == buf_out->buf_end) {
00333               buf_out->buf_end = buf_out->buf_ptr = 0;
00334        }
00335 
00336        return ret;
00337 }
00338 
00339 int
00340 ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
00341 {
00342 #ifdef HAVE_FCNTL
00343        int flags = fcntl( sd, F_GETFL);
00344        if( nb ) {
00345               flags |= O_NONBLOCK;
00346        } else {
00347               flags &= ~O_NONBLOCK;
00348        }
00349        return fcntl( sd, F_SETFL, flags );
00350               
00351 #elif defined( FIONBIO )
00352        ioctl_t status = nb ? 1 : 0;
00353        return ioctl( sd, FIONBIO, &status );
00354 #endif
00355 }
00356 
00357 int
00358 ber_int_sb_init( Sockbuf *sb )
00359 {
00360        assert( sb != NULL);
00361 
00362        sb->sb_valid=LBER_VALID_SOCKBUF;
00363        sb->sb_options = 0;
00364        sb->sb_debug = ber_int_debug;
00365        sb->sb_fd = AC_SOCKET_INVALID;
00366        sb->sb_iod = NULL;
00367        sb->sb_trans_needs_read = 0;
00368        sb->sb_trans_needs_write = 0;
00369    
00370        assert( SOCKBUF_VALID( sb ) );
00371        return 0;
00372 }
00373    
00374 int
00375 ber_int_sb_close( Sockbuf *sb )
00376 {
00377        Sockbuf_IO_Desc             *p;
00378 
00379        assert( sb != NULL);
00380    
00381        p = sb->sb_iod;
00382        while ( p ) {
00383               if ( p->sbiod_io->sbi_close && p->sbiod_io->sbi_close( p ) < 0 ) {
00384                      return -1;
00385               }
00386               p = p->sbiod_next;
00387        }
00388    
00389        sb->sb_fd = AC_SOCKET_INVALID;
00390    
00391        return 0;
00392 }
00393 
00394 int
00395 ber_int_sb_destroy( Sockbuf *sb )
00396 {
00397        Sockbuf_IO_Desc             *p;
00398 
00399        assert( sb != NULL);
00400        assert( SOCKBUF_VALID( sb ) );
00401    
00402        while ( sb->sb_iod ) {
00403               p = sb->sb_iod->sbiod_next;
00404               ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io,
00405                      sb->sb_iod->sbiod_level );
00406               sb->sb_iod = p;
00407        }
00408 
00409        return ber_int_sb_init( sb );
00410 }
00411 
00412 ber_slen_t
00413 ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len )
00414 {
00415        ber_slen_t           ret;
00416 
00417        assert( buf != NULL );
00418        assert( sb != NULL);
00419        assert( sb->sb_iod != NULL );
00420        assert( SOCKBUF_VALID( sb ) );
00421 
00422        for (;;) {
00423               ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len );
00424 
00425 #ifdef EINTR  
00426               if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
00427 #endif
00428               break;
00429        }
00430 
00431        return ret;
00432 }
00433 
00434 ber_slen_t
00435 ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len )
00436 {
00437        ber_slen_t           ret;
00438 
00439        assert( buf != NULL );
00440        assert( sb != NULL);
00441        assert( sb->sb_iod != NULL );
00442        assert( SOCKBUF_VALID( sb ) );
00443 
00444        for (;;) {
00445               ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len );
00446 
00447 #ifdef EINTR  
00448               if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
00449 #endif
00450               break;
00451        }
00452 
00453        return ret;
00454 }
00455 
00456 /*
00457  * Support for TCP
00458  */
00459 
00460 static ber_slen_t
00461 sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
00462 {
00463        assert( sbiod != NULL);
00464        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
00465 
00466 #if defined(MACOS)
00467 /*
00468  * MacTCP/OpenTransport
00469  */
00470        return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf,
00471               len, NULL );
00472 
00473 #elif defined( HAVE_PCNFS ) || \
00474    defined( HAVE_WINSOCK ) || defined ( __BEOS__ )
00475 /*
00476  * PCNFS (under DOS)
00477  */
00478 /*
00479  * Windows Socket API (under DOS/Windows 3.x)
00480  */
00481 /*
00482  * 32-bit Windows Socket API (under Windows NT or Windows 95)
00483  */
00484        return recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
00485 
00486 #elif defined( HAVE_NCSA )
00487 /*
00488  * NCSA Telnet TCP/IP stack (under DOS)
00489  */
00490        return nread( sbiod->sbiod_sb->sb_fd, buf, len );
00491 
00492 #else
00493        return read( sbiod->sbiod_sb->sb_fd, buf, len );
00494 #endif
00495 }
00496 
00497 static ber_slen_t
00498 sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
00499 {
00500        assert( sbiod != NULL);
00501        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
00502 
00503 #if defined(MACOS) 
00504 /*
00505  * MacTCP/OpenTransport
00506  */
00507 #define MAX_WRITE    65535
00508        return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf,
00509               (len<MAX_WRITE) ? len : MAX_WRITE );
00510 
00511 #elif defined( HAVE_PCNFS) \
00512        || defined( HAVE_WINSOCK) || defined ( __BEOS__ )
00513 /*
00514  * PCNFS (under DOS)
00515  */
00516 /*
00517  * Windows Socket API (under DOS/Windows 3.x)
00518  */
00519 /*
00520  * 32-bit Windows Socket API (under Windows NT or Windows 95)
00521  */
00522        return send( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
00523 
00524 #elif defined(HAVE_NCSA)
00525        return netwrite( sbiod->sbiod_sb->sb_fd, buf, len );
00526 
00527 #elif defined(VMS)
00528 /*
00529  * VMS -- each write must be 64K or smaller
00530  */
00531 #define MAX_WRITE 65535
00532        return write( sbiod->sbiod_sb->sb_fd, buf,
00533               (len<MAX_WRITE) ? len : MAX_WRITE);
00534 #else
00535        return write( sbiod->sbiod_sb->sb_fd, buf, len );
00536 #endif   
00537 }   
00538    
00539 static int 
00540 sb_stream_close( Sockbuf_IO_Desc *sbiod )
00541 {
00542        assert( sbiod != NULL );
00543        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
00544        if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
00545               tcp_close( sbiod->sbiod_sb->sb_fd );
00546    return 0;
00547 }
00548 
00549 /* The argument is a pointer to the socket descriptor */
00550 static int
00551 sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
00552        assert( sbiod != NULL );
00553 
00554        if ( arg != NULL ) {
00555               sbiod->sbiod_sb->sb_fd = *((int *)arg);
00556        }
00557        return 0;
00558 }
00559 
00560 static int
00561 sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
00562        /* This is an end IO descriptor */
00563        return 0;
00564 }
00565 
00566 Sockbuf_IO ber_sockbuf_io_tcp = {
00567        sb_stream_setup,     /* sbi_setup */
00568        NULL,                       /* sbi_remove */
00569        sb_stream_ctrl,             /* sbi_ctrl */
00570        sb_stream_read,             /* sbi_read */
00571        sb_stream_write,     /* sbi_write */
00572        sb_stream_close             /* sbi_close */
00573 };
00574 
00575 
00576 /*
00577  * Support for readahead (UDP needs it)
00578  */
00579 
00580 static int
00581 sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg )
00582 {
00583        Sockbuf_Buf          *p;
00584 
00585        assert( sbiod != NULL );
00586 
00587        p = LBER_MALLOC( sizeof( *p ) );
00588        if ( p == NULL ) return -1;
00589 
00590        ber_pvt_sb_buf_init( p );
00591 
00592        if ( arg == NULL ) {
00593               ber_pvt_sb_grow_buffer( p, LBER_DEFAULT_READAHEAD );
00594        } else {
00595               ber_pvt_sb_grow_buffer( p, *((int *)arg) );
00596        }
00597 
00598        sbiod->sbiod_pvt = p;
00599        return 0;
00600 }
00601 
00602 static int
00603 sb_rdahead_remove( Sockbuf_IO_Desc *sbiod )
00604 {
00605        Sockbuf_Buf          *p;
00606 
00607        assert( sbiod != NULL );
00608 
00609        p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
00610 
00611        if ( p->buf_ptr != p->buf_end ) return -1;
00612 
00613        ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) );
00614        LBER_FREE( sbiod->sbiod_pvt );
00615        sbiod->sbiod_pvt = NULL;
00616 
00617        return 0;
00618 }
00619 
00620 static ber_slen_t
00621 sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
00622 {
00623        Sockbuf_Buf          *p;
00624        ber_slen_t           bufptr = 0, ret, max;
00625 
00626        assert( sbiod != NULL );
00627        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
00628        assert( sbiod->sbiod_next != NULL );
00629 
00630        p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
00631 
00632        assert( p->buf_size > 0 );
00633 
00634        /* Are there anything left in the buffer? */
00635        ret = ber_pvt_sb_copy_out( p, buf, len );
00636        bufptr += ret;
00637        len -= ret;
00638 
00639        if ( len == 0 ) return bufptr;
00640 
00641        max = p->buf_size - p->buf_end;
00642        ret = 0;
00643        while ( max > 0 ) {
00644               ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end,
00645                      max );
00646 #ifdef EINTR  
00647               if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
00648 #endif
00649               break;
00650        }
00651 
00652        if ( ret < 0 ) {
00653               return ( bufptr ? bufptr : ret );
00654        }
00655 
00656        p->buf_end += ret;
00657        bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len );
00658        return bufptr;
00659 }
00660 
00661 static ber_slen_t
00662 sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
00663 {
00664        assert( sbiod != NULL );
00665        assert( sbiod->sbiod_next != NULL );
00666 
00667        return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
00668 }
00669 
00670 static int
00671 sb_rdahead_close( Sockbuf_IO_Desc *sbiod )
00672 {
00673        assert( sbiod != NULL );
00674 
00675        /* Just erase the buffer */
00676        ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt);
00677        return 0;
00678 }
00679 
00680 static int
00681 sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
00682 {
00683        Sockbuf_Buf          *p;
00684 
00685        p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
00686 
00687        if ( opt == LBER_SB_OPT_DATA_READY ) {
00688               if ( p->buf_ptr != p->buf_end ) {
00689                      return 1;
00690               }
00691 
00692        } else if ( opt == LBER_SB_OPT_SET_READAHEAD ) {
00693               if ( p->buf_size >= *((ber_len_t *)arg) ) {
00694                      return 0;
00695               }
00696               return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ?
00697                      -1 : 1 );
00698        }
00699 
00700        return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
00701 }
00702 
00703 Sockbuf_IO ber_sockbuf_io_readahead = {
00704        sb_rdahead_setup,    /* sbi_setup */
00705        sb_rdahead_remove,   /* sbi_remove */
00706        sb_rdahead_ctrl,     /* sbi_ctrl */
00707        sb_rdahead_read,     /* sbi_read */
00708        sb_rdahead_write,    /* sbi_write */
00709        sb_rdahead_close     /* sbi_close */
00710 };
00711 
00712 /*
00713  * Support for simple file IO
00714  */
00715 
00716 static ber_slen_t
00717 sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
00718 {
00719        assert( sbiod != NULL);
00720        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
00721 
00722 #ifdef LDAP_PF_LOCAL_SENDMSG
00723        if ( sbiod->sbiod_sb->sb_ungetlen ) {
00724               ber_len_t blen = sbiod->sbiod_sb->sb_ungetlen;
00725               if ( blen > len )
00726                      blen = len;
00727               AC_MEMCPY( buf, sbiod->sbiod_sb->sb_ungetbuf, blen );
00728               buf = (char *) buf + blen;
00729               len -= blen;
00730               sbiod->sbiod_sb->sb_ungetlen -= blen;
00731               if ( sbiod->sbiod_sb->sb_ungetlen ) {
00732                      AC_MEMCPY( sbiod->sbiod_sb->sb_ungetbuf,
00733                             sbiod->sbiod_sb->sb_ungetbuf+blen,
00734                             sbiod->sbiod_sb->sb_ungetlen );
00735               }
00736               if ( len == 0 )
00737                      return blen;
00738        }
00739 #endif
00740        return read( sbiod->sbiod_sb->sb_fd, buf, len );
00741 }
00742 
00743 static ber_slen_t
00744 sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
00745 {
00746        assert( sbiod != NULL);
00747        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
00748 
00749        return write( sbiod->sbiod_sb->sb_fd, buf, len );
00750 }
00751 
00752 static int 
00753 sb_fd_close( Sockbuf_IO_Desc *sbiod )
00754 {   
00755        assert( sbiod != NULL );
00756        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
00757 
00758        if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
00759               close( sbiod->sbiod_sb->sb_fd );
00760        return 0;
00761 }
00762 
00763 /* The argument is a pointer to the file descriptor */
00764 static int
00765 sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
00766        assert( sbiod != NULL );
00767 
00768        if ( arg != NULL )
00769               sbiod->sbiod_sb->sb_fd = *((int *)arg);
00770        return 0;
00771 }
00772 
00773 static int
00774 sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
00775        /* This is an end IO descriptor */
00776        return 0;
00777 }
00778 
00779 Sockbuf_IO ber_sockbuf_io_fd = {
00780        sb_fd_setup,  /* sbi_setup */
00781        NULL,                /* sbi_remove */
00782        sb_fd_ctrl,          /* sbi_ctrl */
00783        sb_fd_read,          /* sbi_read */
00784        sb_fd_write,         /* sbi_write */
00785        sb_fd_close          /* sbi_close */
00786 };
00787 
00788 /*
00789  * Debugging layer
00790  */
00791 
00792 static int
00793 sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg )
00794 {
00795        assert( sbiod != NULL );
00796        
00797        if ( arg == NULL ) arg = "sockbuf_";
00798 
00799        sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 );
00800        if ( sbiod->sbiod_pvt == NULL ) return -1;
00801 
00802        strcpy( (char *)sbiod->sbiod_pvt, (char *)arg );
00803        return 0;
00804 }
00805 
00806 static int
00807 sb_debug_remove( Sockbuf_IO_Desc *sbiod )
00808 {
00809        assert( sbiod != NULL );
00810        assert( sbiod->sbiod_pvt != NULL );
00811 
00812        LBER_FREE( sbiod->sbiod_pvt );
00813        sbiod->sbiod_pvt = NULL;
00814        return 0;
00815 }
00816 
00817 static int
00818 sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
00819 {
00820        return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
00821 }
00822 
00823 static ber_slen_t
00824 sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
00825 {
00826        ber_slen_t           ret;
00827        char ebuf[128];
00828 
00829        ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len );
00830        if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) {
00831               int err = sock_errno();
00832               if ( ret < 0 ) {
00833                      ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
00834                             "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt,
00835                             (long)len, AC_STRERROR_R( err, ebuf, sizeof ebuf ) );
00836               } else {
00837                      ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
00838                             "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt,
00839                             (long)len, (long)ret );
00840                      ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
00841                             (const char *)buf, ret );
00842               }
00843               sock_errset(err);
00844        }
00845        return ret;
00846 }
00847 
00848 static ber_slen_t
00849 sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
00850 {
00851        ber_slen_t           ret;
00852        char ebuf[128];
00853 
00854        ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
00855        if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) {
00856               int err = sock_errno();
00857               if ( ret < 0 ) {
00858                      ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
00859                             "%swrite: want=%ld error=%s\n",
00860                             (char *)sbiod->sbiod_pvt, (long)len,
00861                             AC_STRERROR_R( err, ebuf, sizeof ebuf ) );
00862               } else {
00863                      ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
00864                             "%swrite: want=%ld, written=%ld\n",
00865                             (char *)sbiod->sbiod_pvt, (long)len, (long)ret );
00866                      ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
00867                             (const char *)buf, ret );
00868               }
00869               sock_errset(err);
00870        }
00871 
00872        return ret;
00873 }
00874 
00875 Sockbuf_IO ber_sockbuf_io_debug = {
00876        sb_debug_setup,             /* sbi_setup */
00877        sb_debug_remove,     /* sbi_remove */
00878        sb_debug_ctrl,              /* sbi_ctrl */
00879        sb_debug_read,              /* sbi_read */
00880        sb_debug_write,             /* sbi_write */
00881        NULL                        /* sbi_close */
00882 };
00883 
00884 #ifdef LDAP_CONNECTIONLESS
00885 
00886 /*
00887  * Support for UDP (CLDAP)
00888  *
00889  * All I/O at this level must be atomic. For ease of use, the sb_readahead
00890  * must be used above this module. All data reads and writes are prefixed
00891  * with a sockaddr containing the address of the remote entity. Upper levels
00892  * must read and write this sockaddr before doing the usual ber_printf/scanf
00893  * operations on LDAP messages.
00894  */
00895 
00896 static int 
00897 sb_dgram_setup( Sockbuf_IO_Desc *sbiod, void *arg )
00898 {
00899        assert( sbiod != NULL);
00900        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
00901 
00902        if ( arg != NULL ) sbiod->sbiod_sb->sb_fd = *((int *)arg);
00903        return 0;
00904 }
00905 
00906 static ber_slen_t
00907 sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
00908 {
00909        ber_slen_t rc;
00910        ber_socklen_t addrlen;
00911        struct sockaddr *src;
00912    
00913        assert( sbiod != NULL );
00914        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
00915        assert( buf != NULL );
00916 
00917        addrlen = sizeof( struct sockaddr );
00918        src = buf;
00919        buf = (char *) buf + addrlen;
00920        len -= addrlen;
00921        rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, src, &addrlen );
00922 
00923        return rc > 0 ? rc+sizeof(struct sockaddr) : rc;
00924 }
00925 
00926 static ber_slen_t 
00927 sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
00928 {
00929        ber_slen_t rc;
00930        struct sockaddr *dst;
00931    
00932        assert( sbiod != NULL );
00933        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
00934        assert( buf != NULL );
00935 
00936        dst = buf;
00937        buf = (char *) buf + sizeof( struct sockaddr );
00938        len -= sizeof( struct sockaddr );
00939    
00940        rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, dst,
00941               sizeof( struct sockaddr ) );
00942 
00943        if ( rc < 0 ) return -1;
00944    
00945        /* fake error if write was not atomic */
00946        if (rc < len) {
00947 # ifdef EMSGSIZE
00948               errno = EMSGSIZE;
00949 # endif
00950               return -1;
00951        }
00952        rc = len + sizeof(struct sockaddr);
00953        return rc;
00954 }
00955 
00956 static int 
00957 sb_dgram_close( Sockbuf_IO_Desc *sbiod )
00958 {
00959        assert( sbiod != NULL );
00960        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
00961   
00962        if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
00963               tcp_close( sbiod->sbiod_sb->sb_fd );
00964        return 0;
00965 }
00966 
00967 static int
00968 sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
00969 {
00970        /* This is an end IO descriptor */
00971        return 0;
00972 }
00973 
00974 Sockbuf_IO ber_sockbuf_io_udp =
00975 {
00976        sb_dgram_setup,             /* sbi_setup */
00977        NULL,                /* sbi_remove */
00978        sb_dgram_ctrl,              /* sbi_ctrl */
00979        sb_dgram_read,              /* sbi_read */
00980        sb_dgram_write,             /* sbi_write */
00981        sb_dgram_close              /* sbi_close */
00982 };
00983 
00984 #endif /* LDAP_CONNECTIONLESS */