1 /* $NetBSD: sockbuf.c,v 1.3 2021/08/14 16:14:55 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-2021 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.3 2021/08/14 16:14:55 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 *
ber_sockbuf_alloc(void)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
ber_sockbuf_free(Sockbuf * sb)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
ber_sockbuf_ctrl(Sockbuf * sb,int opt,void * arg)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
ber_sockbuf_add_io(Sockbuf * sb,Sockbuf_IO * sbio,int layer,void * arg)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
ber_sockbuf_remove_io(Sockbuf * sb,Sockbuf_IO * sbio,int layer)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
ber_pvt_sb_buf_init(Sockbuf_Buf * buf)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
ber_pvt_sb_buf_destroy(Sockbuf_Buf * buf)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
ber_pvt_sb_grow_buffer(Sockbuf_Buf * buf,ber_len_t minsize)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
ber_pvt_sb_copy_out(Sockbuf_Buf * sbb,char * buf,ber_len_t len)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
ber_pvt_sb_do_write(Sockbuf_IO_Desc * sbiod,Sockbuf_Buf * buf_out)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
ber_pvt_socket_set_nonblock(ber_socket_t sd,int nb)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
ber_int_sb_init(Sockbuf * sb)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
ber_int_sb_close(Sockbuf * sb)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
ber_int_sb_destroy(Sockbuf * sb)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
ber_int_sb_read(Sockbuf * sb,void * buf,ber_len_t len)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
ber_int_sb_write(Sockbuf * sb,void * buf,ber_len_t len)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
sb_stream_read(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)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
sb_stream_write(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)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
sb_stream_close(Sockbuf_IO_Desc * sbiod)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
sb_stream_setup(Sockbuf_IO_Desc * sbiod,void * arg)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
sb_stream_ctrl(Sockbuf_IO_Desc * sbiod,int opt,void * arg)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
sb_rdahead_setup(Sockbuf_IO_Desc * sbiod,void * arg)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
sb_rdahead_remove(Sockbuf_IO_Desc * sbiod)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
sb_rdahead_read(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)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
sb_rdahead_write(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)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
sb_rdahead_close(Sockbuf_IO_Desc * sbiod)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
sb_rdahead_ctrl(Sockbuf_IO_Desc * sbiod,int opt,void * arg)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
sb_fd_read(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)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
sb_fd_write(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)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
sb_fd_close(Sockbuf_IO_Desc * sbiod)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
sb_fd_setup(Sockbuf_IO_Desc * sbiod,void * arg)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
sb_fd_ctrl(Sockbuf_IO_Desc * sbiod,int opt,void * arg)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
sb_debug_setup(Sockbuf_IO_Desc * sbiod,void * arg)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
sb_debug_remove(Sockbuf_IO_Desc * sbiod)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
sb_debug_ctrl(Sockbuf_IO_Desc * sbiod,int opt,void * arg)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
sb_debug_read(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)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
sb_debug_write(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)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
sb_dgram_setup(Sockbuf_IO_Desc * sbiod,void * arg)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
sb_dgram_read(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)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
sb_dgram_write(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)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
sb_dgram_close(Sockbuf_IO_Desc * sbiod)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
sb_dgram_ctrl(Sockbuf_IO_Desc * sbiod,int opt,void * arg)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