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