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