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