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