1 /* $NetBSD: sockbuf.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $ */ 2 3 /* sockbuf.c - i/o routines with support for adding i/o layers. */ 4 /* OpenLDAP: pkg/ldap/libraries/liblber/sockbuf.c,v 1.65.2.5 2009/01/22 00:00:54 kurt Exp */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2009 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 57 Sockbuf * 58 ber_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 70 void 71 ber_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 */ 84 int 85 ber_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 177 int 178 ber_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 215 int 216 ber_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 246 void 247 ber_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 255 void 256 ber_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 266 int 267 ber_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 287 ber_len_t 288 ber_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 310 ber_slen_t 311 ber_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 341 int 342 ber_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 359 int 360 ber_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 376 int 377 ber_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 396 int 397 ber_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 414 ber_slen_t 415 ber_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 436 ber_slen_t 437 ber_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 462 static ber_slen_t 463 sb_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 499 static ber_slen_t 500 sb_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 541 static int 542 sb_stream_close( Sockbuf_IO_Desc *sbiod ) 543 { 544 assert( sbiod != NULL ); 545 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 546 tcp_close( sbiod->sbiod_sb->sb_fd ); 547 return 0; 548 } 549 550 /* The argument is a pointer to the socket descriptor */ 551 static int 552 sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) { 553 assert( sbiod != NULL ); 554 555 if ( arg != NULL ) { 556 sbiod->sbiod_sb->sb_fd = *((int *)arg); 557 } 558 return 0; 559 } 560 561 static int 562 sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { 563 /* This is an end IO descriptor */ 564 return 0; 565 } 566 567 Sockbuf_IO ber_sockbuf_io_tcp = { 568 sb_stream_setup, /* sbi_setup */ 569 NULL, /* sbi_remove */ 570 sb_stream_ctrl, /* sbi_ctrl */ 571 sb_stream_read, /* sbi_read */ 572 sb_stream_write, /* sbi_write */ 573 sb_stream_close /* sbi_close */ 574 }; 575 576 577 /* 578 * Support for readahead (UDP needs it) 579 */ 580 581 static int 582 sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg ) 583 { 584 Sockbuf_Buf *p; 585 586 assert( sbiod != NULL ); 587 588 p = LBER_MALLOC( sizeof( *p ) ); 589 if ( p == NULL ) return -1; 590 591 ber_pvt_sb_buf_init( p ); 592 593 if ( arg == NULL ) { 594 ber_pvt_sb_grow_buffer( p, LBER_DEFAULT_READAHEAD ); 595 } else { 596 ber_pvt_sb_grow_buffer( p, *((int *)arg) ); 597 } 598 599 sbiod->sbiod_pvt = p; 600 return 0; 601 } 602 603 static int 604 sb_rdahead_remove( Sockbuf_IO_Desc *sbiod ) 605 { 606 Sockbuf_Buf *p; 607 608 assert( sbiod != NULL ); 609 610 p = (Sockbuf_Buf *)sbiod->sbiod_pvt; 611 612 if ( p->buf_ptr != p->buf_end ) return -1; 613 614 ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) ); 615 LBER_FREE( sbiod->sbiod_pvt ); 616 sbiod->sbiod_pvt = NULL; 617 618 return 0; 619 } 620 621 static ber_slen_t 622 sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) 623 { 624 Sockbuf_Buf *p; 625 ber_slen_t bufptr = 0, ret, max; 626 627 assert( sbiod != NULL ); 628 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 629 assert( sbiod->sbiod_next != NULL ); 630 631 p = (Sockbuf_Buf *)sbiod->sbiod_pvt; 632 633 assert( p->buf_size > 0 ); 634 635 /* Are there anything left in the buffer? */ 636 ret = ber_pvt_sb_copy_out( p, buf, len ); 637 bufptr += ret; 638 len -= ret; 639 640 if ( len == 0 ) return bufptr; 641 642 max = p->buf_size - p->buf_end; 643 ret = 0; 644 while ( max > 0 ) { 645 ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end, 646 max ); 647 #ifdef EINTR 648 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue; 649 #endif 650 break; 651 } 652 653 if ( ret < 0 ) { 654 return ( bufptr ? bufptr : ret ); 655 } 656 657 p->buf_end += ret; 658 bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len ); 659 return bufptr; 660 } 661 662 static ber_slen_t 663 sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) 664 { 665 assert( sbiod != NULL ); 666 assert( sbiod->sbiod_next != NULL ); 667 668 return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ); 669 } 670 671 static int 672 sb_rdahead_close( Sockbuf_IO_Desc *sbiod ) 673 { 674 assert( sbiod != NULL ); 675 676 /* Just erase the buffer */ 677 ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt); 678 return 0; 679 } 680 681 static int 682 sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) 683 { 684 Sockbuf_Buf *p; 685 686 p = (Sockbuf_Buf *)sbiod->sbiod_pvt; 687 688 if ( opt == LBER_SB_OPT_DATA_READY ) { 689 if ( p->buf_ptr != p->buf_end ) { 690 return 1; 691 } 692 693 } else if ( opt == LBER_SB_OPT_SET_READAHEAD ) { 694 if ( p->buf_size >= *((ber_len_t *)arg) ) { 695 return 0; 696 } 697 return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ? 698 -1 : 1 ); 699 } 700 701 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); 702 } 703 704 Sockbuf_IO ber_sockbuf_io_readahead = { 705 sb_rdahead_setup, /* sbi_setup */ 706 sb_rdahead_remove, /* sbi_remove */ 707 sb_rdahead_ctrl, /* sbi_ctrl */ 708 sb_rdahead_read, /* sbi_read */ 709 sb_rdahead_write, /* sbi_write */ 710 sb_rdahead_close /* sbi_close */ 711 }; 712 713 /* 714 * Support for simple file IO 715 */ 716 717 static ber_slen_t 718 sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) 719 { 720 assert( sbiod != NULL); 721 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 722 723 #ifdef LDAP_PF_LOCAL_SENDMSG 724 if ( sbiod->sbiod_sb->sb_ungetlen ) { 725 ber_len_t blen = sbiod->sbiod_sb->sb_ungetlen; 726 if ( blen > len ) 727 blen = len; 728 AC_MEMCPY( buf, sbiod->sbiod_sb->sb_ungetbuf, blen ); 729 buf = (char *) buf + blen; 730 len -= blen; 731 sbiod->sbiod_sb->sb_ungetlen -= blen; 732 if ( sbiod->sbiod_sb->sb_ungetlen ) { 733 AC_MEMCPY( sbiod->sbiod_sb->sb_ungetbuf, 734 sbiod->sbiod_sb->sb_ungetbuf+blen, 735 sbiod->sbiod_sb->sb_ungetlen ); 736 } 737 if ( len == 0 ) 738 return blen; 739 } 740 #endif 741 return read( sbiod->sbiod_sb->sb_fd, buf, len ); 742 } 743 744 static ber_slen_t 745 sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) 746 { 747 assert( sbiod != NULL); 748 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 749 750 return write( sbiod->sbiod_sb->sb_fd, buf, len ); 751 } 752 753 static int 754 sb_fd_close( Sockbuf_IO_Desc *sbiod ) 755 { 756 assert( sbiod != NULL ); 757 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 758 759 close( sbiod->sbiod_sb->sb_fd ); 760 return 0; 761 } 762 763 /* The argument is a pointer to the file descriptor */ 764 static int 765 sb_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 773 static int 774 sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { 775 /* This is an end IO descriptor */ 776 return 0; 777 } 778 779 Sockbuf_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 792 static int 793 sb_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 806 static int 807 sb_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 817 static int 818 sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) 819 { 820 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); 821 } 822 823 static ber_slen_t 824 sb_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 848 static ber_slen_t 849 sb_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 875 Sockbuf_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 896 static int 897 sb_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 906 static ber_slen_t 907 sb_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 926 static ber_slen_t 927 sb_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 956 static int 957 sb_dgram_close( Sockbuf_IO_Desc *sbiod ) 958 { 959 assert( sbiod != NULL ); 960 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); 961 962 tcp_close( sbiod->sbiod_sb->sb_fd ); 963 return 0; 964 } 965 966 static int 967 sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) 968 { 969 /* This is an end IO descriptor */ 970 return 0; 971 } 972 973 Sockbuf_IO ber_sockbuf_io_udp = 974 { 975 sb_dgram_setup, /* sbi_setup */ 976 NULL, /* sbi_remove */ 977 sb_dgram_ctrl, /* sbi_ctrl */ 978 sb_dgram_read, /* sbi_read */ 979 sb_dgram_write, /* sbi_write */ 980 sb_dgram_close /* sbi_close */ 981 }; 982 983 #endif /* LDAP_CONNECTIONLESS */ 984