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