1/* sockbuf.c - i/o routines with support for adding i/o layers. */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2011 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 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>. 15 */ 16 17#include "portable.h" 18 19#include <stdio.h> 20 21#include <ac/stdlib.h> 22 23#include <ac/ctype.h> 24#include <ac/errno.h> 25#include <ac/socket.h> 26#include <ac/string.h> 27#include <ac/unistd.h> 28 29#ifdef HAVE_IO_H 30#include <io.h> 31#endif /* HAVE_IO_H */ 32 33#if defined( HAVE_FCNTL_H ) 34#include <fcntl.h> 35#endif 36 37#if defined( HAVE_SYS_FILIO_H ) 38#include <sys/filio.h> 39#elif defined( HAVE_SYS_IOCTL_H ) 40#include <sys/ioctl.h> 41#endif 42 43#include "lber-int.h" 44 45#ifndef LBER_MIN_BUFF_SIZE 46#define LBER_MIN_BUFF_SIZE 4096 47#endif 48#ifndef LBER_MAX_BUFF_SIZE 49#define LBER_MAX_BUFF_SIZE (65536*256) 50#endif 51#ifndef LBER_DEFAULT_READAHEAD 52#define LBER_DEFAULT_READAHEAD 16384 53#endif 54 55Sockbuf * 56ber_sockbuf_alloc( void ) 57{ 58 Sockbuf *sb; 59 60 sb = LBER_CALLOC( 1, sizeof( Sockbuf ) ); 61 62 if( sb == NULL ) return NULL; 63 64 ber_int_sb_init( sb ); 65 return sb; 66} 67 68void 69ber_sockbuf_free( Sockbuf *sb ) 70{ 71 assert( sb != NULL ); 72 assert( SOCKBUF_VALID( sb ) ); 73 74 ber_int_sb_close( sb ); 75 ber_int_sb_destroy( sb ); 76 LBER_FREE( sb ); 77} 78 79/* Return values: -1: error, 0: no operation performed or the answer is false, 80 * 1: successful operation or the answer is true 81 */ 82int 83ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg ) 84{ 85 Sockbuf_IO_Desc *p; 86 int ret = 0; 87 88 assert( sb != NULL ); 89 assert( SOCKBUF_VALID( sb ) ); 90 91 switch ( opt ) { 92 case LBER_SB_OPT_HAS_IO: 93 p = sb->sb_iod; 94 while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) { 95 p = p->sbiod_next; 96 } 97 98 if ( p ) { 99 ret = 1; 100 } 101 break; 102 103 case LBER_SB_OPT_GET_FD: 104 if ( arg != NULL ) { 105 *((ber_socket_t *)arg) = sb->sb_fd; 106 } 107 ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1); 108 break; 109 110 case LBER_SB_OPT_SET_FD: 111 sb->sb_fd = *((ber_socket_t *)arg); 112 ret = 1; 113 break; 114 115 case LBER_SB_OPT_SET_NONBLOCK: 116 ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL) 117 ? -1 : 1; 118 break; 119 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 123 */ 124 char buf[LBER_MIN_BUFF_SIZE]; 125 126 do { 127 ret = ber_int_sb_read( sb, buf, sizeof( buf ) ); 128 } while ( ret == sizeof( buf ) ); 129 130 ret = 1; 131 } break; 132 133 case LBER_SB_OPT_NEEDS_READ: 134 ret = ( sb->sb_trans_needs_read ? 1 : 0 ); 135 break; 136 137 case LBER_SB_OPT_NEEDS_WRITE: 138 ret = ( sb->sb_trans_needs_write ? 1 : 0 ); 139 break; 140 141 case LBER_SB_OPT_GET_MAX_INCOMING: 142 if ( arg != NULL ) { 143 *((ber_len_t *)arg) = sb->sb_max_incoming; 144 } 145 ret = 1; 146 break; 147 148 case LBER_SB_OPT_SET_MAX_INCOMING: 149 sb->sb_max_incoming = *((ber_len_t *)arg); 150 ret = 1; 151 break; 152 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, 158 sb->sb_ungetlen ); 159 ret = 1; 160 } else { 161 sb->sb_ungetlen = 0; 162 ret = -1; 163 } 164#endif 165 break; 166 167 default: 168 ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, opt, arg ); 169 break; 170 } 171 172 return ret; 173} 174 175int 176ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg ) 177{ 178 Sockbuf_IO_Desc *d, *p, **q; 179 180 assert( sb != NULL ); 181 assert( SOCKBUF_VALID( sb ) ); 182 183 if ( sbio == NULL ) { 184 return -1; 185 } 186 187 q = &sb->sb_iod; 188 p = *q; 189 while ( p && p->sbiod_level > layer ) { 190 q = &p->sbiod_next; 191 p = *q; 192 } 193 194 d = LBER_MALLOC( sizeof( *d ) ); 195 if ( d == NULL ) { 196 return -1; 197 } 198 199 d->sbiod_level = layer; 200 d->sbiod_sb = sb; 201 d->sbiod_io = sbio; 202 memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) ); 203 d->sbiod_next = p; 204 *q = d; 205 206 if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) ) { 207 return -1; 208 } 209 210 return 0; 211} 212 213int 214ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer ) 215{ 216 Sockbuf_IO_Desc *p, **q; 217 218 assert( sb != NULL ); 219 assert( SOCKBUF_VALID( sb ) ); 220 221 if ( sb->sb_iod == NULL ) { 222 return -1; 223 } 224 225 q = &sb->sb_iod; 226 while ( *q != NULL ) { 227 p = *q; 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 ) 231 { 232 return -1; 233 } 234 *q = p->sbiod_next; 235 LBER_FREE( p ); 236 break; 237 } 238 q = &p->sbiod_next; 239 } 240 241 return 0; 242} 243 244void 245ber_pvt_sb_buf_init( Sockbuf_Buf *buf ) 246{ 247 buf->buf_base = NULL; 248 buf->buf_ptr = 0; 249 buf->buf_end = 0; 250 buf->buf_size = 0; 251} 252 253void 254ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf ) 255{ 256 assert( buf != NULL); 257 258 if (buf->buf_base) { 259 LBER_FREE( buf->buf_base ); 260 } 261 ber_pvt_sb_buf_init( buf ); 262} 263 264int 265ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize ) 266{ 267 ber_len_t pw; 268 char *p; 269 270 assert( buf != NULL ); 271 272 for ( pw = LBER_MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) { 273 if (pw > LBER_MAX_BUFF_SIZE) return -1; 274 } 275 276 if ( buf->buf_size < pw ) { 277 p = LBER_REALLOC( buf->buf_base, pw ); 278 if ( p == NULL ) return -1; 279 buf->buf_base = p; 280 buf->buf_size = pw; 281 } 282 return 0; 283} 284 285ber_len_t 286ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len ) 287{ 288 ber_len_t max; 289 290 assert( buf != NULL ); 291 assert( sbb != NULL ); 292#if 0 293 assert( sbb->buf_size > 0 ); 294#endif 295 296 max = sbb->buf_end - sbb->buf_ptr; 297 max = ( max < len) ? max : len; 298 if ( max ) { 299 AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max ); 300 sbb->buf_ptr += max; 301 if ( sbb->buf_ptr >= sbb->buf_end ) { 302 sbb->buf_ptr = sbb->buf_end = 0; 303 } 304 } 305 return max; 306} 307 308ber_slen_t 309ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out ) 310{ 311 ber_len_t to_go; 312 ber_slen_t ret; 313 314 assert( sbiod != NULL ); 315 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 316 317 to_go = buf_out->buf_end - buf_out->buf_ptr; 318 assert( to_go > 0 ); 319 320 for(;;) { 321 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base + 322 buf_out->buf_ptr, to_go ); 323#ifdef EINTR 324 if ((ret<0) && (errno==EINTR)) continue; 325#endif 326 break; 327 } 328 329 if ( ret <= 0 ) return ret; 330 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; 334 } 335 336 return ret; 337} 338 339int 340ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb ) 341{ 342#ifdef HAVE_FCNTL 343 int flags = fcntl( sd, F_GETFL); 344 if( nb ) { 345 flags |= O_NONBLOCK; 346 } else { 347 flags &= ~O_NONBLOCK; 348 } 349 return fcntl( sd, F_SETFL, flags ); 350 351#elif defined( FIONBIO ) 352 ioctl_t status = nb ? 1 : 0; 353 return ioctl( sd, FIONBIO, &status ); 354#endif 355} 356 357int 358ber_int_sb_init( Sockbuf *sb ) 359{ 360 assert( sb != NULL); 361 362 sb->sb_valid=LBER_VALID_SOCKBUF; 363 sb->sb_options = 0; 364 sb->sb_debug = ber_int_debug; 365 sb->sb_fd = AC_SOCKET_INVALID; 366 sb->sb_iod = NULL; 367 sb->sb_trans_needs_read = 0; 368 sb->sb_trans_needs_write = 0; 369 370 assert( SOCKBUF_VALID( sb ) ); 371 return 0; 372} 373 374int 375ber_int_sb_close( Sockbuf *sb ) 376{ 377 Sockbuf_IO_Desc *p; 378 379 assert( sb != NULL); 380 381 p = sb->sb_iod; 382 while ( p ) { 383 if ( p->sbiod_io->sbi_close && p->sbiod_io->sbi_close( p ) < 0 ) { 384 return -1; 385 } 386 p = p->sbiod_next; 387 } 388 389 sb->sb_fd = AC_SOCKET_INVALID; 390 391 return 0; 392} 393 394int 395ber_int_sb_destroy( Sockbuf *sb ) 396{ 397 Sockbuf_IO_Desc *p; 398 399 assert( sb != NULL); 400 assert( SOCKBUF_VALID( sb ) ); 401 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 ); 406 sb->sb_iod = p; 407 } 408 409 return ber_int_sb_init( sb ); 410} 411 412ber_slen_t 413ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len ) 414{ 415 ber_slen_t ret; 416 417 assert( buf != NULL ); 418 assert( sb != NULL); 419 assert( sb->sb_iod != NULL ); 420 assert( SOCKBUF_VALID( sb ) ); 421 422 for (;;) { 423 ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len ); 424 425#ifdef EINTR 426 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue; 427#endif 428 break; 429 } 430 431 return ret; 432} 433 434ber_slen_t 435ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len ) 436{ 437 ber_slen_t ret; 438 439 assert( buf != NULL ); 440 assert( sb != NULL); 441 assert( sb->sb_iod != NULL ); 442 assert( SOCKBUF_VALID( sb ) ); 443 444 for (;;) { 445 ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len ); 446 447#ifdef EINTR 448 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue; 449#endif 450 break; 451 } 452 453 return ret; 454} 455 456/* 457 * Support for TCP 458 */ 459 460static ber_slen_t 461sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) 462{ 463 assert( sbiod != NULL); 464 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 465 466#if defined(MACOS) 467/* 468 * MacTCP/OpenTransport 469 */ 470 return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf, 471 len, NULL ); 472 473#elif defined( HAVE_PCNFS ) || \ 474 defined( HAVE_WINSOCK ) || defined ( __BEOS__ ) 475/* 476 * PCNFS (under DOS) 477 */ 478/* 479 * Windows Socket API (under DOS/Windows 3.x) 480 */ 481/* 482 * 32-bit Windows Socket API (under Windows NT or Windows 95) 483 */ 484 return recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 ); 485 486#elif defined( HAVE_NCSA ) 487/* 488 * NCSA Telnet TCP/IP stack (under DOS) 489 */ 490 return nread( sbiod->sbiod_sb->sb_fd, buf, len ); 491 492#else 493 return read( sbiod->sbiod_sb->sb_fd, buf, len ); 494#endif 495} 496 497static ber_slen_t 498sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) 499{ 500 assert( sbiod != NULL); 501 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 502 503#if defined(MACOS) 504/* 505 * MacTCP/OpenTransport 506 */ 507#define MAX_WRITE 65535 508 return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf, 509 (len<MAX_WRITE) ? len : MAX_WRITE ); 510 511#elif defined( HAVE_PCNFS) \ 512 || defined( HAVE_WINSOCK) || defined ( __BEOS__ ) 513/* 514 * PCNFS (under DOS) 515 */ 516/* 517 * Windows Socket API (under DOS/Windows 3.x) 518 */ 519/* 520 * 32-bit Windows Socket API (under Windows NT or Windows 95) 521 */ 522 return send( sbiod->sbiod_sb->sb_fd, buf, len, 0 ); 523 524#elif defined(HAVE_NCSA) 525 return netwrite( sbiod->sbiod_sb->sb_fd, buf, len ); 526 527#elif defined(VMS) 528/* 529 * VMS -- each write must be 64K or smaller 530 */ 531#define MAX_WRITE 65535 532 return write( sbiod->sbiod_sb->sb_fd, buf, 533 (len<MAX_WRITE) ? len : MAX_WRITE); 534#else 535 return write( sbiod->sbiod_sb->sb_fd, buf, len ); 536#endif 537} 538 539static int 540sb_stream_close( Sockbuf_IO_Desc *sbiod ) 541{ 542 assert( sbiod != NULL ); 543 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 544 if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID ) 545 tcp_close( sbiod->sbiod_sb->sb_fd ); 546 return 0; 547} 548 549/* The argument is a pointer to the socket descriptor */ 550static int 551sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { 552 assert( sbiod != NULL ); 553 554 if ( arg != NULL ) { 555 sbiod->sbiod_sb->sb_fd = *((int *)arg); 556 } 557 return 0; 558} 559 560static int 561sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { 562 /* This is an end IO descriptor */ 563 return 0; 564} 565 566Sockbuf_IO ber_sockbuf_io_tcp = { 567 sb_stream_setup, /* sbi_setup */ 568 NULL, /* sbi_remove */ 569 sb_stream_ctrl, /* sbi_ctrl */ 570 sb_stream_read, /* sbi_read */ 571 sb_stream_write, /* sbi_write */ 572 sb_stream_close /* sbi_close */ 573}; 574 575 576/* 577 * Support for readahead (UDP needs it) 578 */ 579 580static int 581sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg ) 582{ 583 Sockbuf_Buf *p; 584 585 assert( sbiod != NULL ); 586 587 p = LBER_MALLOC( sizeof( *p ) ); 588 if ( p == NULL ) return -1; 589 590 ber_pvt_sb_buf_init( p ); 591 592 if ( arg == NULL ) { 593 ber_pvt_sb_grow_buffer( p, LBER_DEFAULT_READAHEAD ); 594 } else { 595 ber_pvt_sb_grow_buffer( p, *((int *)arg) ); 596 } 597 598 sbiod->sbiod_pvt = p; 599 return 0; 600} 601 602static int 603sb_rdahead_remove( Sockbuf_IO_Desc *sbiod ) 604{ 605 Sockbuf_Buf *p; 606 607 assert( sbiod != NULL ); 608 609 p = (Sockbuf_Buf *)sbiod->sbiod_pvt; 610 611 if ( p->buf_ptr != p->buf_end ) return -1; 612 613 ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) ); 614 LBER_FREE( sbiod->sbiod_pvt ); 615 sbiod->sbiod_pvt = NULL; 616 617 return 0; 618} 619 620static ber_slen_t 621sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) 622{ 623 Sockbuf_Buf *p; 624 ber_slen_t bufptr = 0, ret, max; 625 626 assert( sbiod != NULL ); 627 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 628 assert( sbiod->sbiod_next != NULL ); 629 630 p = (Sockbuf_Buf *)sbiod->sbiod_pvt; 631 632 assert( p->buf_size > 0 ); 633 634 /* Are there anything left in the buffer? */ 635 ret = ber_pvt_sb_copy_out( p, buf, len ); 636 bufptr += ret; 637 len -= ret; 638 639 if ( len == 0 ) return bufptr; 640 641 max = p->buf_size - p->buf_end; 642 ret = 0; 643 while ( max > 0 ) { 644 ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end, 645 max ); 646#ifdef EINTR 647 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue; 648#endif 649 break; 650 } 651 652 if ( ret < 0 ) { 653 return ( bufptr ? bufptr : ret ); 654 } 655 656 p->buf_end += ret; 657 bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len ); 658 return bufptr; 659} 660 661static ber_slen_t 662sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) 663{ 664 assert( sbiod != NULL ); 665 assert( sbiod->sbiod_next != NULL ); 666 667 return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ); 668} 669 670static int 671sb_rdahead_close( Sockbuf_IO_Desc *sbiod ) 672{ 673 assert( sbiod != NULL ); 674 675 /* Just erase the buffer */ 676 ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt); 677 return 0; 678} 679 680static int 681sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) 682{ 683 Sockbuf_Buf *p; 684 685 p = (Sockbuf_Buf *)sbiod->sbiod_pvt; 686 687 if ( opt == LBER_SB_OPT_DATA_READY ) { 688 if ( p->buf_ptr != p->buf_end ) { 689 return 1; 690 } 691 692 } else if ( opt == LBER_SB_OPT_SET_READAHEAD ) { 693 if ( p->buf_size >= *((ber_len_t *)arg) ) { 694 return 0; 695 } 696 return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ? 697 -1 : 1 ); 698 } 699 700 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); 701} 702 703Sockbuf_IO ber_sockbuf_io_readahead = { 704 sb_rdahead_setup, /* sbi_setup */ 705 sb_rdahead_remove, /* sbi_remove */ 706 sb_rdahead_ctrl, /* sbi_ctrl */ 707 sb_rdahead_read, /* sbi_read */ 708 sb_rdahead_write, /* sbi_write */ 709 sb_rdahead_close /* sbi_close */ 710}; 711 712/* 713 * Support for simple file IO 714 */ 715 716static ber_slen_t 717sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) 718{ 719 assert( sbiod != NULL); 720 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 721 722#ifdef LDAP_PF_LOCAL_SENDMSG 723 if ( sbiod->sbiod_sb->sb_ungetlen ) { 724 ber_len_t blen = sbiod->sbiod_sb->sb_ungetlen; 725 if ( blen > len ) 726 blen = len; 727 AC_MEMCPY( buf, sbiod->sbiod_sb->sb_ungetbuf, blen ); 728 buf = (char *) buf + blen; 729 len -= blen; 730 sbiod->sbiod_sb->sb_ungetlen -= blen; 731 if ( sbiod->sbiod_sb->sb_ungetlen ) { 732 AC_MEMCPY( sbiod->sbiod_sb->sb_ungetbuf, 733 sbiod->sbiod_sb->sb_ungetbuf+blen, 734 sbiod->sbiod_sb->sb_ungetlen ); 735 } 736 if ( len == 0 ) 737 return blen; 738 } 739#endif 740 return read( sbiod->sbiod_sb->sb_fd, buf, len ); 741} 742 743static ber_slen_t 744sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) 745{ 746 assert( sbiod != NULL); 747 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 748 749 return write( sbiod->sbiod_sb->sb_fd, buf, len ); 750} 751 752static int 753sb_fd_close( Sockbuf_IO_Desc *sbiod ) 754{ 755 assert( sbiod != NULL ); 756 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 757 758 if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID ) 759 close( sbiod->sbiod_sb->sb_fd ); 760 return 0; 761} 762 763/* The argument is a pointer to the file descriptor */ 764static int 765sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { 766 assert( sbiod != NULL ); 767 768 if ( arg != NULL ) 769 sbiod->sbiod_sb->sb_fd = *((int *)arg); 770 return 0; 771} 772 773static int 774sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { 775 /* This is an end IO descriptor */ 776 return 0; 777} 778 779Sockbuf_IO ber_sockbuf_io_fd = { 780 sb_fd_setup, /* sbi_setup */ 781 NULL, /* sbi_remove */ 782 sb_fd_ctrl, /* sbi_ctrl */ 783 sb_fd_read, /* sbi_read */ 784 sb_fd_write, /* sbi_write */ 785 sb_fd_close /* sbi_close */ 786}; 787 788/* 789 * Debugging layer 790 */ 791 792static int 793sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg ) 794{ 795 assert( sbiod != NULL ); 796 797 if ( arg == NULL ) arg = "sockbuf_"; 798 799 sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 ); 800 if ( sbiod->sbiod_pvt == NULL ) return -1; 801 802 strcpy( (char *)sbiod->sbiod_pvt, (char *)arg ); 803 return 0; 804} 805 806static int 807sb_debug_remove( Sockbuf_IO_Desc *sbiod ) 808{ 809 assert( sbiod != NULL ); 810 assert( sbiod->sbiod_pvt != NULL ); 811 812 LBER_FREE( sbiod->sbiod_pvt ); 813 sbiod->sbiod_pvt = NULL; 814 return 0; 815} 816 817static int 818sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) 819{ 820 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); 821} 822 823static ber_slen_t 824sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) 825{ 826 ber_slen_t ret; 827 char ebuf[128]; 828 829 ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len ); 830 if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) { 831 int err = sock_errno(); 832 if ( ret < 0 ) { 833 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, 834 "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt, 835 (long)len, AC_STRERROR_R( err, ebuf, sizeof ebuf ) ); 836 } else { 837 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, 838 "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt, 839 (long)len, (long)ret ); 840 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, 841 (const char *)buf, ret ); 842 } 843 sock_errset(err); 844 } 845 return ret; 846} 847 848static ber_slen_t 849sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) 850{ 851 ber_slen_t ret; 852 char ebuf[128]; 853 854 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ); 855 if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) { 856 int err = sock_errno(); 857 if ( ret < 0 ) { 858 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, 859 "%swrite: want=%ld error=%s\n", 860 (char *)sbiod->sbiod_pvt, (long)len, 861 AC_STRERROR_R( err, ebuf, sizeof ebuf ) ); 862 } else { 863 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, 864 "%swrite: want=%ld, written=%ld\n", 865 (char *)sbiod->sbiod_pvt, (long)len, (long)ret ); 866 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, 867 (const char *)buf, ret ); 868 } 869 sock_errset(err); 870 } 871 872 return ret; 873} 874 875Sockbuf_IO ber_sockbuf_io_debug = { 876 sb_debug_setup, /* sbi_setup */ 877 sb_debug_remove, /* sbi_remove */ 878 sb_debug_ctrl, /* sbi_ctrl */ 879 sb_debug_read, /* sbi_read */ 880 sb_debug_write, /* sbi_write */ 881 NULL /* sbi_close */ 882}; 883 884#ifdef LDAP_CONNECTIONLESS 885 886/* 887 * Support for UDP (CLDAP) 888 * 889 * All I/O at this level must be atomic. For ease of use, the sb_readahead 890 * must be used above this module. All data reads and writes are prefixed 891 * with a sockaddr containing the address of the remote entity. Upper levels 892 * must read and write this sockaddr before doing the usual ber_printf/scanf 893 * operations on LDAP messages. 894 */ 895 896static int 897sb_dgram_setup( Sockbuf_IO_Desc *sbiod, void *arg ) 898{ 899 assert( sbiod != NULL); 900 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 901 902 if ( arg != NULL ) sbiod->sbiod_sb->sb_fd = *((int *)arg); 903 return 0; 904} 905 906static ber_slen_t 907sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) 908{ 909 ber_slen_t rc; 910 ber_socklen_t addrlen; 911 struct sockaddr *src; 912 913 assert( sbiod != NULL ); 914 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 915 assert( buf != NULL ); 916 917 addrlen = sizeof( struct sockaddr ); 918 src = buf; 919 buf = (char *) buf + addrlen; 920 len -= addrlen; 921 rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, src, &addrlen ); 922 923 return rc > 0 ? rc+sizeof(struct sockaddr) : rc; 924} 925 926static ber_slen_t 927sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) 928{ 929 ber_slen_t rc; 930 struct sockaddr *dst; 931 932 assert( sbiod != NULL ); 933 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 934 assert( buf != NULL ); 935 936 dst = buf; 937 buf = (char *) buf + sizeof( struct sockaddr ); 938 len -= sizeof( struct sockaddr ); 939 940 rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, dst, 941 sizeof( struct sockaddr ) ); 942 943 if ( rc < 0 ) return -1; 944 945 /* fake error if write was not atomic */ 946 if (rc < len) { 947# ifdef EMSGSIZE 948 errno = EMSGSIZE; 949# endif 950 return -1; 951 } 952 rc = len + sizeof(struct sockaddr); 953 return rc; 954} 955 956static int 957sb_dgram_close( Sockbuf_IO_Desc *sbiod ) 958{ 959 assert( sbiod != NULL ); 960 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 961 962 if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID ) 963 tcp_close( sbiod->sbiod_sb->sb_fd ); 964 return 0; 965} 966 967static int 968sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) 969{ 970 /* This is an end IO descriptor */ 971 return 0; 972} 973 974Sockbuf_IO ber_sockbuf_io_udp = 975{ 976 sb_dgram_setup, /* sbi_setup */ 977 NULL, /* sbi_remove */ 978 sb_dgram_ctrl, /* sbi_ctrl */ 979 sb_dgram_read, /* sbi_read */ 980 sb_dgram_write, /* sbi_write */ 981 sb_dgram_close /* sbi_close */ 982}; 983 984#endif /* LDAP_CONNECTIONLESS */ 985