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