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