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