1 /* sockbuf.c - i/o routines with support for adding i/o layers. */
2 /* $OpenLDAP: pkg/ldap/libraries/liblber/sockbuf.c,v 1.65.2.4 2008/02/11 23:26:41 kurt Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
21 #include <ac/stdlib.h>
25 #include <ac/socket.h>
26 #include <ac/string.h>
27 #include <ac/unistd.h>
31 #endif /* HAVE_IO_H */
33 #if defined( HAVE_FCNTL_H )
37 #if defined( HAVE_SYS_FILIO_H )
38 #include <sys/filio.h>
39 #elif defined( HAVE_SYS_IOCTL_H )
40 #include <sys/ioctl.h>
45 #ifndef LBER_MIN_BUFF_SIZE
46 #define LBER_MIN_BUFF_SIZE 4096
48 #ifndef LBER_MAX_BUFF_SIZE
49 #define LBER_MAX_BUFF_SIZE (65536*256)
51 #ifndef LBER_DEFAULT_READAHEAD
52 #define LBER_DEFAULT_READAHEAD 16384
56 ber_sockbuf_alloc( void )
60 sb
= LBER_CALLOC( 1, sizeof( Sockbuf
) );
62 if( sb
== NULL
) return NULL
;
64 ber_int_sb_init( sb
);
69 ber_sockbuf_free( Sockbuf
*sb
)
72 assert( SOCKBUF_VALID( sb
) );
74 ber_int_sb_close( sb
);
75 ber_int_sb_destroy( sb
);
79 /* Return values: -1: error, 0: no operation performed or the answer is false,
80 * 1: successful operation or the answer is true
83 ber_sockbuf_ctrl( Sockbuf
*sb
, int opt
, void *arg
)
89 assert( SOCKBUF_VALID( sb
) );
92 case LBER_SB_OPT_HAS_IO
:
94 while ( p
&& p
->sbiod_io
!= (Sockbuf_IO
*)arg
) {
103 case LBER_SB_OPT_GET_FD
:
105 *((ber_socket_t
*)arg
) = sb
->sb_fd
;
107 ret
= ( sb
->sb_fd
== AC_SOCKET_INVALID
? -1 : 1);
110 case LBER_SB_OPT_SET_FD
:
111 sb
->sb_fd
= *((ber_socket_t
*)arg
);
115 case LBER_SB_OPT_SET_NONBLOCK
:
116 ret
= ber_pvt_socket_set_nonblock( sb
->sb_fd
, arg
!= NULL
)
120 case LBER_SB_OPT_DRAIN
: {
121 /* Drain the data source to enable possible errors (e.g.
122 * TLS) to be propagated to the upper layers
124 char buf
[LBER_MIN_BUFF_SIZE
];
127 ret
= ber_int_sb_read( sb
, buf
, sizeof( buf
) );
128 } while ( ret
== sizeof( buf
) );
133 case LBER_SB_OPT_NEEDS_READ
:
134 ret
= ( sb
->sb_trans_needs_read
? 1 : 0 );
137 case LBER_SB_OPT_NEEDS_WRITE
:
138 ret
= ( sb
->sb_trans_needs_write
? 1 : 0 );
141 case LBER_SB_OPT_GET_MAX_INCOMING
:
143 *((ber_len_t
*)arg
) = sb
->sb_max_incoming
;
148 case LBER_SB_OPT_SET_MAX_INCOMING
:
149 sb
->sb_max_incoming
= *((ber_len_t
*)arg
);
153 case LBER_SB_OPT_UNGET_BUF
:
154 #ifdef LDAP_PF_LOCAL_SENDMSG
155 sb
->sb_ungetlen
= ((struct berval
*)arg
)->bv_len
;
156 if ( sb
->sb_ungetlen
<= sizeof( sb
->sb_ungetbuf
)) {
157 AC_MEMCPY( sb
->sb_ungetbuf
, ((struct berval
*)arg
)->bv_val
,
168 ret
= sb
->sb_iod
->sbiod_io
->sbi_ctrl( sb
->sb_iod
, opt
, arg
);
176 ber_sockbuf_add_io( Sockbuf
*sb
, Sockbuf_IO
*sbio
, int layer
, void *arg
)
178 Sockbuf_IO_Desc
*d
, *p
, **q
;
180 assert( sb
!= NULL
);
181 assert( SOCKBUF_VALID( sb
) );
183 if ( sbio
== NULL
) {
189 while ( p
&& p
->sbiod_level
> layer
) {
194 d
= LBER_MALLOC( sizeof( *d
) );
199 d
->sbiod_level
= layer
;
202 memset( &d
->sbiod_pvt
, '\0', sizeof( d
->sbiod_pvt
) );
206 if ( sbio
->sbi_setup
!= NULL
&& ( sbio
->sbi_setup( d
, arg
) < 0 ) ) {
214 ber_sockbuf_remove_io( Sockbuf
*sb
, Sockbuf_IO
*sbio
, int layer
)
216 Sockbuf_IO_Desc
*p
, **q
;
218 assert( sb
!= NULL
);
219 assert( SOCKBUF_VALID( sb
) );
221 if ( sb
->sb_iod
== NULL
) {
226 while ( *q
!= NULL
) {
228 if ( layer
== p
->sbiod_level
&& p
->sbiod_io
== sbio
) {
229 if ( p
->sbiod_io
->sbi_remove
!= NULL
&&
230 p
->sbiod_io
->sbi_remove( p
) < 0 )
245 ber_pvt_sb_buf_init( Sockbuf_Buf
*buf
)
247 buf
->buf_base
= NULL
;
254 ber_pvt_sb_buf_destroy( Sockbuf_Buf
*buf
)
256 assert( buf
!= NULL
);
259 LBER_FREE( buf
->buf_base
);
261 ber_pvt_sb_buf_init( buf
);
265 ber_pvt_sb_grow_buffer( Sockbuf_Buf
*buf
, ber_len_t minsize
)
270 assert( buf
!= NULL
);
272 for ( pw
= LBER_MIN_BUFF_SIZE
; pw
< minsize
; pw
<<= 1 ) {
273 if (pw
> LBER_MAX_BUFF_SIZE
) return -1;
276 if ( buf
->buf_size
< pw
) {
277 p
= LBER_REALLOC( buf
->buf_base
, pw
);
278 if ( p
== NULL
) return -1;
286 ber_pvt_sb_copy_out( Sockbuf_Buf
*sbb
, char *buf
, ber_len_t len
)
290 assert( buf
!= NULL
);
291 assert( sbb
!= NULL
);
293 assert( sbb
->buf_size
> 0 );
296 max
= sbb
->buf_end
- sbb
->buf_ptr
;
297 max
= ( max
< len
) ? max
: len
;
299 AC_MEMCPY( buf
, sbb
->buf_base
+ sbb
->buf_ptr
, max
);
301 if ( sbb
->buf_ptr
>= sbb
->buf_end
) {
302 sbb
->buf_ptr
= sbb
->buf_end
= 0;
309 ber_pvt_sb_do_write( Sockbuf_IO_Desc
*sbiod
, Sockbuf_Buf
*buf_out
)
314 assert( sbiod
!= NULL
);
315 assert( SOCKBUF_VALID( sbiod
->sbiod_sb
) );
317 to_go
= buf_out
->buf_end
- buf_out
->buf_ptr
;
321 ret
= LBER_SBIOD_WRITE_NEXT( sbiod
, buf_out
->buf_base
+
322 buf_out
->buf_ptr
, to_go
);
324 if ((ret
<0) && (errno
==EINTR
)) continue;
329 if ( ret
<= 0 ) return ret
;
331 buf_out
->buf_ptr
+= ret
;
332 if (buf_out
->buf_ptr
== buf_out
->buf_end
) {
333 buf_out
->buf_end
= buf_out
->buf_ptr
= 0;
340 ber_pvt_socket_set_nonblock( ber_socket_t sd
, int nb
)
343 int flags
= fcntl( sd
, F_GETFL
);
347 flags
&= ~O_NONBLOCK
;
349 return fcntl( sd
, F_SETFL
, flags
);
351 #elif defined( FIONBIO )
352 ioctl_t status
= nb
? 1 : 0;
353 return ioctl( sd
, FIONBIO
, &status
);
358 ber_int_sb_init( Sockbuf
*sb
)
362 sb
->sb_valid
=LBER_VALID_SOCKBUF
;
364 sb
->sb_debug
= ber_int_debug
;
365 sb
->sb_fd
= AC_SOCKET_INVALID
;
367 sb
->sb_trans_needs_read
= 0;
368 sb
->sb_trans_needs_write
= 0;
370 assert( SOCKBUF_VALID( sb
) );
375 ber_int_sb_close( Sockbuf
*sb
)
383 if ( p
->sbiod_io
->sbi_close
&& p
->sbiod_io
->sbi_close( p
) < 0 ) {
389 sb
->sb_fd
= AC_SOCKET_INVALID
;
395 ber_int_sb_destroy( Sockbuf
*sb
)
400 assert( SOCKBUF_VALID( sb
) );
402 while ( sb
->sb_iod
) {
403 p
= sb
->sb_iod
->sbiod_next
;
404 ber_sockbuf_remove_io( sb
, sb
->sb_iod
->sbiod_io
,
405 sb
->sb_iod
->sbiod_level
);
409 return ber_int_sb_init( sb
);
413 ber_int_sb_read( Sockbuf
*sb
, void *buf
, ber_len_t len
)
417 assert( buf
!= NULL
);
419 assert( sb
->sb_iod
!= NULL
);
420 assert( SOCKBUF_VALID( sb
) );
423 ret
= sb
->sb_iod
->sbiod_io
->sbi_read( sb
->sb_iod
, buf
, len
);
426 if ( ( ret
< 0 ) && ( errno
== EINTR
) ) continue;
435 ber_int_sb_write( Sockbuf
*sb
, void *buf
, ber_len_t len
)
439 assert( buf
!= NULL
);
441 assert( sb
->sb_iod
!= NULL
);
442 assert( SOCKBUF_VALID( sb
) );
445 ret
= sb
->sb_iod
->sbiod_io
->sbi_write( sb
->sb_iod
, buf
, len
);
448 if ( ( ret
< 0 ) && ( errno
== EINTR
) ) continue;
461 sb_stream_read( Sockbuf_IO_Desc
*sbiod
, void *buf
, ber_len_t len
)
463 assert( sbiod
!= NULL
);
464 assert( SOCKBUF_VALID( sbiod
->sbiod_sb
) );
468 * MacTCP/OpenTransport
470 return tcpread( sbiod
->sbiod_sb
->sb_fd
, 0, (unsigned char *)buf
,
473 #elif defined( HAVE_PCNFS ) || \
474 defined( HAVE_WINSOCK ) || defined ( __BEOS__ )
479 * Windows Socket API (under DOS/Windows 3.x)
482 * 32-bit Windows Socket API (under Windows NT or Windows 95)
484 return recv( sbiod
->sbiod_sb
->sb_fd
, buf
, len
, 0 );
486 #elif defined( HAVE_NCSA )
488 * NCSA Telnet TCP/IP stack (under DOS)
490 return nread( sbiod
->sbiod_sb
->sb_fd
, buf
, len
);
493 return read( sbiod
->sbiod_sb
->sb_fd
, buf
, len
);
498 sb_stream_write( Sockbuf_IO_Desc
*sbiod
, void *buf
, ber_len_t len
)
500 assert( sbiod
!= NULL
);
501 assert( SOCKBUF_VALID( sbiod
->sbiod_sb
) );
505 * MacTCP/OpenTransport
507 #define MAX_WRITE 65535
508 return tcpwrite( sbiod
->sbiod_sb
->sb_fd
, (unsigned char *)buf
,
509 (len
<MAX_WRITE
) ? len
: MAX_WRITE
);
511 #elif defined( HAVE_PCNFS) \
512 || defined( HAVE_WINSOCK) || defined ( __BEOS__ )
517 * Windows Socket API (under DOS/Windows 3.x)
520 * 32-bit Windows Socket API (under Windows NT or Windows 95)
522 return send( sbiod
->sbiod_sb
->sb_fd
, buf
, len
, 0 );
524 #elif defined(HAVE_NCSA)
525 return netwrite( sbiod
->sbiod_sb
->sb_fd
, buf
, len
);
529 * VMS -- each write must be 64K or smaller
531 #define MAX_WRITE 65535
532 return write( sbiod
->sbiod_sb
->sb_fd
, buf
,
533 (len
<MAX_WRITE
) ? len
: MAX_WRITE
);
535 return write( sbiod
->sbiod_sb
->sb_fd
, buf
, len
);
540 sb_stream_close( Sockbuf_IO_Desc
*sbiod
)
542 assert( sbiod
!= NULL
);
543 assert( SOCKBUF_VALID( sbiod
->sbiod_sb
) );
544 tcp_close( sbiod
->sbiod_sb
->sb_fd
);
548 /* The argument is a pointer to the socket descriptor */
550 sb_stream_setup( Sockbuf_IO_Desc
*sbiod
, void *arg
) {
551 assert( sbiod
!= NULL
);
554 sbiod
->sbiod_sb
->sb_fd
= *((int *)arg
);
560 sb_stream_ctrl( Sockbuf_IO_Desc
*sbiod
, int opt
, void *arg
) {
561 /* This is an end IO descriptor */
565 Sockbuf_IO ber_sockbuf_io_tcp
= {
566 sb_stream_setup
, /* sbi_setup */
567 NULL
, /* sbi_remove */
568 sb_stream_ctrl
, /* sbi_ctrl */
569 sb_stream_read
, /* sbi_read */
570 sb_stream_write
, /* sbi_write */
571 sb_stream_close
/* sbi_close */
576 * Support for readahead (UDP needs it)
580 sb_rdahead_setup( Sockbuf_IO_Desc
*sbiod
, void *arg
)
584 assert( sbiod
!= NULL
);
586 p
= LBER_MALLOC( sizeof( *p
) );
587 if ( p
== NULL
) return -1;
589 ber_pvt_sb_buf_init( p
);
592 ber_pvt_sb_grow_buffer( p
, LBER_DEFAULT_READAHEAD
);
594 ber_pvt_sb_grow_buffer( p
, *((int *)arg
) );
597 sbiod
->sbiod_pvt
= p
;
602 sb_rdahead_remove( Sockbuf_IO_Desc
*sbiod
)
606 assert( sbiod
!= NULL
);
608 p
= (Sockbuf_Buf
*)sbiod
->sbiod_pvt
;
610 if ( p
->buf_ptr
!= p
->buf_end
) return -1;
612 ber_pvt_sb_buf_destroy( (Sockbuf_Buf
*)(sbiod
->sbiod_pvt
) );
613 LBER_FREE( sbiod
->sbiod_pvt
);
614 sbiod
->sbiod_pvt
= NULL
;
620 sb_rdahead_read( Sockbuf_IO_Desc
*sbiod
, void *buf
, ber_len_t len
)
623 ber_slen_t bufptr
= 0, ret
, max
;
625 assert( sbiod
!= NULL
);
626 assert( SOCKBUF_VALID( sbiod
->sbiod_sb
) );
627 assert( sbiod
->sbiod_next
!= NULL
);
629 p
= (Sockbuf_Buf
*)sbiod
->sbiod_pvt
;
631 assert( p
->buf_size
> 0 );
633 /* Are there anything left in the buffer? */
634 ret
= ber_pvt_sb_copy_out( p
, buf
, len
);
638 if ( len
== 0 ) return bufptr
;
640 max
= p
->buf_size
- p
->buf_end
;
643 ret
= LBER_SBIOD_READ_NEXT( sbiod
, p
->buf_base
+ p
->buf_end
,
646 if ( ( ret
< 0 ) && ( errno
== EINTR
) ) continue;
652 return ( bufptr
? bufptr
: ret
);
656 bufptr
+= ber_pvt_sb_copy_out( p
, (char *) buf
+ bufptr
, len
);
661 sb_rdahead_write( Sockbuf_IO_Desc
*sbiod
, void *buf
, ber_len_t len
)
663 assert( sbiod
!= NULL
);
664 assert( sbiod
->sbiod_next
!= NULL
);
666 return LBER_SBIOD_WRITE_NEXT( sbiod
, buf
, len
);
670 sb_rdahead_close( Sockbuf_IO_Desc
*sbiod
)
672 assert( sbiod
!= NULL
);
674 /* Just erase the buffer */
675 ber_pvt_sb_buf_destroy((Sockbuf_Buf
*)sbiod
->sbiod_pvt
);
680 sb_rdahead_ctrl( Sockbuf_IO_Desc
*sbiod
, int opt
, void *arg
)
684 p
= (Sockbuf_Buf
*)sbiod
->sbiod_pvt
;
686 if ( opt
== LBER_SB_OPT_DATA_READY
) {
687 if ( p
->buf_ptr
!= p
->buf_end
) {
691 } else if ( opt
== LBER_SB_OPT_SET_READAHEAD
) {
692 if ( p
->buf_size
>= *((ber_len_t
*)arg
) ) {
695 return ( ber_pvt_sb_grow_buffer( p
, *((int *)arg
) ) ?
699 return LBER_SBIOD_CTRL_NEXT( sbiod
, opt
, arg
);
702 Sockbuf_IO ber_sockbuf_io_readahead
= {
703 sb_rdahead_setup
, /* sbi_setup */
704 sb_rdahead_remove
, /* sbi_remove */
705 sb_rdahead_ctrl
, /* sbi_ctrl */
706 sb_rdahead_read
, /* sbi_read */
707 sb_rdahead_write
, /* sbi_write */
708 sb_rdahead_close
/* sbi_close */
712 * Support for simple file IO
716 sb_fd_read( Sockbuf_IO_Desc
*sbiod
, void *buf
, ber_len_t len
)
718 assert( sbiod
!= NULL
);
719 assert( SOCKBUF_VALID( sbiod
->sbiod_sb
) );
721 #ifdef LDAP_PF_LOCAL_SENDMSG
722 if ( sbiod
->sbiod_sb
->sb_ungetlen
) {
723 ber_len_t blen
= sbiod
->sbiod_sb
->sb_ungetlen
;
726 AC_MEMCPY( buf
, sbiod
->sbiod_sb
->sb_ungetbuf
, blen
);
727 buf
= (char *) buf
+ blen
;
729 sbiod
->sbiod_sb
->sb_ungetlen
-= blen
;
730 if ( sbiod
->sbiod_sb
->sb_ungetlen
) {
731 AC_MEMCPY( sbiod
->sbiod_sb
->sb_ungetbuf
,
732 sbiod
->sbiod_sb
->sb_ungetbuf
+blen
,
733 sbiod
->sbiod_sb
->sb_ungetlen
);
739 return read( sbiod
->sbiod_sb
->sb_fd
, buf
, len
);
743 sb_fd_write( Sockbuf_IO_Desc
*sbiod
, void *buf
, ber_len_t len
)
745 assert( sbiod
!= NULL
);
746 assert( SOCKBUF_VALID( sbiod
->sbiod_sb
) );
748 return write( sbiod
->sbiod_sb
->sb_fd
, buf
, len
);
752 sb_fd_close( Sockbuf_IO_Desc
*sbiod
)
754 assert( sbiod
!= NULL
);
755 assert( SOCKBUF_VALID( sbiod
->sbiod_sb
) );
757 close( sbiod
->sbiod_sb
->sb_fd
);
761 /* The argument is a pointer to the file descriptor */
763 sb_fd_setup( Sockbuf_IO_Desc
*sbiod
, void *arg
) {
764 assert( sbiod
!= NULL
);
767 sbiod
->sbiod_sb
->sb_fd
= *((int *)arg
);
772 sb_fd_ctrl( Sockbuf_IO_Desc
*sbiod
, int opt
, void *arg
) {
773 /* This is an end IO descriptor */
777 Sockbuf_IO ber_sockbuf_io_fd
= {
778 sb_fd_setup
, /* sbi_setup */
779 NULL
, /* sbi_remove */
780 sb_fd_ctrl
, /* sbi_ctrl */
781 sb_fd_read
, /* sbi_read */
782 sb_fd_write
, /* sbi_write */
783 sb_fd_close
/* sbi_close */
791 sb_debug_setup( Sockbuf_IO_Desc
*sbiod
, void *arg
)
793 assert( sbiod
!= NULL
);
795 if ( arg
== NULL
) arg
= "sockbuf_";
797 sbiod
->sbiod_pvt
= LBER_MALLOC( strlen( arg
) + 1 );
798 if ( sbiod
->sbiod_pvt
== NULL
) return -1;
800 strcpy( (char *)sbiod
->sbiod_pvt
, (char *)arg
);
805 sb_debug_remove( Sockbuf_IO_Desc
*sbiod
)
807 assert( sbiod
!= NULL
);
808 assert( sbiod
->sbiod_pvt
!= NULL
);
810 LBER_FREE( sbiod
->sbiod_pvt
);
811 sbiod
->sbiod_pvt
= NULL
;
816 sb_debug_ctrl( Sockbuf_IO_Desc
*sbiod
, int opt
, void *arg
)
818 return LBER_SBIOD_CTRL_NEXT( sbiod
, opt
, arg
);
822 sb_debug_read( Sockbuf_IO_Desc
*sbiod
, void *buf
, ber_len_t len
)
827 ret
= LBER_SBIOD_READ_NEXT( sbiod
, buf
, len
);
828 if (sbiod
->sbiod_sb
->sb_debug
& LDAP_DEBUG_PACKETS
) {
829 int err
= sock_errno();
831 ber_log_printf( LDAP_DEBUG_PACKETS
, sbiod
->sbiod_sb
->sb_debug
,
832 "%sread: want=%ld error=%s\n", (char *)sbiod
->sbiod_pvt
,
833 (long)len
, AC_STRERROR_R( err
, ebuf
, sizeof ebuf
) );
835 ber_log_printf( LDAP_DEBUG_PACKETS
, sbiod
->sbiod_sb
->sb_debug
,
836 "%sread: want=%ld, got=%ld\n", (char *)sbiod
->sbiod_pvt
,
837 (long)len
, (long)ret
);
838 ber_log_bprint( LDAP_DEBUG_PACKETS
, sbiod
->sbiod_sb
->sb_debug
,
839 (const char *)buf
, ret
);
847 sb_debug_write( Sockbuf_IO_Desc
*sbiod
, void *buf
, ber_len_t len
)
852 ret
= LBER_SBIOD_WRITE_NEXT( sbiod
, buf
, len
);
853 if (sbiod
->sbiod_sb
->sb_debug
& LDAP_DEBUG_PACKETS
) {
854 int err
= sock_errno();
856 ber_log_printf( LDAP_DEBUG_PACKETS
, sbiod
->sbiod_sb
->sb_debug
,
857 "%swrite: want=%ld error=%s\n",
858 (char *)sbiod
->sbiod_pvt
, (long)len
,
859 AC_STRERROR_R( err
, ebuf
, sizeof ebuf
) );
861 ber_log_printf( LDAP_DEBUG_PACKETS
, sbiod
->sbiod_sb
->sb_debug
,
862 "%swrite: want=%ld, written=%ld\n",
863 (char *)sbiod
->sbiod_pvt
, (long)len
, (long)ret
);
864 ber_log_bprint( LDAP_DEBUG_PACKETS
, sbiod
->sbiod_sb
->sb_debug
,
865 (const char *)buf
, ret
);
873 Sockbuf_IO ber_sockbuf_io_debug
= {
874 sb_debug_setup
, /* sbi_setup */
875 sb_debug_remove
, /* sbi_remove */
876 sb_debug_ctrl
, /* sbi_ctrl */
877 sb_debug_read
, /* sbi_read */
878 sb_debug_write
, /* sbi_write */
882 #ifdef LDAP_CONNECTIONLESS
885 * Support for UDP (CLDAP)
887 * All I/O at this level must be atomic. For ease of use, the sb_readahead
888 * must be used above this module. All data reads and writes are prefixed
889 * with a sockaddr containing the address of the remote entity. Upper levels
890 * must read and write this sockaddr before doing the usual ber_printf/scanf
891 * operations on LDAP messages.
895 sb_dgram_setup( Sockbuf_IO_Desc
*sbiod
, void *arg
)
897 assert( sbiod
!= NULL
);
898 assert( SOCKBUF_VALID( sbiod
->sbiod_sb
) );
900 if ( arg
!= NULL
) sbiod
->sbiod_sb
->sb_fd
= *((int *)arg
);
905 sb_dgram_read( Sockbuf_IO_Desc
*sbiod
, void *buf
, ber_len_t len
)
908 ber_socklen_t addrlen
;
909 struct sockaddr
*src
;
911 assert( sbiod
!= NULL
);
912 assert( SOCKBUF_VALID( sbiod
->sbiod_sb
) );
913 assert( buf
!= NULL
);
915 addrlen
= sizeof( struct sockaddr
);
917 buf
= (char *) buf
+ addrlen
;
919 rc
= recvfrom( sbiod
->sbiod_sb
->sb_fd
, buf
, len
, 0, src
, &addrlen
);
921 return rc
> 0 ? rc
+sizeof(struct sockaddr
) : rc
;
925 sb_dgram_write( Sockbuf_IO_Desc
*sbiod
, void *buf
, ber_len_t len
)
928 struct sockaddr
*dst
;
930 assert( sbiod
!= NULL
);
931 assert( SOCKBUF_VALID( sbiod
->sbiod_sb
) );
932 assert( buf
!= NULL
);
935 buf
= (char *) buf
+ sizeof( struct sockaddr
);
936 len
-= sizeof( struct sockaddr
);
938 rc
= sendto( sbiod
->sbiod_sb
->sb_fd
, buf
, len
, 0, dst
,
939 sizeof( struct sockaddr
) );
941 if ( rc
< 0 ) return -1;
943 /* fake error if write was not atomic */
950 rc
= len
+ sizeof(struct sockaddr
);
955 sb_dgram_close( Sockbuf_IO_Desc
*sbiod
)
957 assert( sbiod
!= NULL
);
958 assert( SOCKBUF_VALID( sbiod
->sbiod_sb
) );
960 tcp_close( sbiod
->sbiod_sb
->sb_fd
);
965 sb_dgram_ctrl( Sockbuf_IO_Desc
*sbiod
, int opt
, void *arg
)
967 /* This is an end IO descriptor */
971 Sockbuf_IO ber_sockbuf_io_udp
=
973 sb_dgram_setup
, /* sbi_setup */
974 NULL
, /* sbi_remove */
975 sb_dgram_ctrl
, /* sbi_ctrl */
976 sb_dgram_read
, /* sbi_read */
977 sb_dgram_write
, /* sbi_write */
978 sb_dgram_close
/* sbi_close */
981 #endif /* LDAP_CONNECTIONLESS */