]> git.sur5r.net Git - openldap/blob - libraries/liblber/sockbuf.c
c68c1d89006ec1ad637768e2fd1cc376a476b993
[openldap] / libraries / liblber / sockbuf.c
1 /* sockbuf.c - i/o routines with support for adding i/o layers. */
2 /*
3  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #include <ac/stdlib.h>
12
13 #include <ac/ctype.h>
14 #include <ac/errno.h>
15 #include <ac/socket.h>
16 #include <ac/string.h>
17 #include <ac/unistd.h>
18
19 #ifdef HAVE_IO_H
20 #include <io.h>
21 #endif /* HAVE_IO_H */
22
23 #if defined( HAVE_SYS_FILIO_H )
24 #include <sys/filio.h>
25 #elif defined( HAVE_SYS_IOCTL_H )
26 #include <sys/ioctl.h>
27 #endif
28
29 #undef LDAP_F_PRE
30 #define LDAP_F_PRE LDAP_F_EXPORT
31
32 #include "lber-int.h"
33
34 #ifdef LDAP_TEST
35 #undef TEST_PARTIAL_READ
36 #undef TEST_PARTIAL_WRITE
37 #endif
38
39 #define MAX_BUF_SIZE    65535
40 #define MIN_BUF_SIZE    4096
41
42 #define sockbuf_io_write( sb, buf, len ) \
43 ((sb)->sb_io->sbi_write( (sb), (buf), (len) ))
44
45 #define sockbuf_io_read( sb, buf, len ) \
46 ((sb)->sb_io->sbi_read( (sb), (buf), (len) ))
47
48 static ber_slen_t have_no_read( Sockbuf *sb, void *buf, ber_len_t len );
49 static ber_slen_t have_no_write( Sockbuf *sb, void *buf, ber_len_t len );
50 static int have_no_close( Sockbuf *sb );
51
52 static Sockbuf_IO sb_IO_None=
53 {
54         NULL,   /* sbi_setup */
55         NULL,   /* sbi_release */
56         have_no_read,   /* sbi_read */
57         have_no_write,  /* sbi_write */
58         have_no_close   /* sbi_close */
59 };
60
61 static void
62 update_status( Sockbuf *sb )
63 {
64         assert( sb != NULL );
65         assert( SOCKBUF_VALID( sb ) );
66
67    sb->sb_buf_ready = (sb->sb_buf.buf_ptr < sb->sb_buf.buf_end);
68 #ifdef USE_SASL   
69    sb->sb_sec_ready = ((sb->sb_sec_buf_in.buf_end!=0) &&
70                        (sb->sb_sec_buf_in.buf_ptr >= 
71                         sb->sb_sec_buf_in.buf_end));
72 #endif   
73 }
74
75 #ifdef LDAP_DEBUG
76 static int 
77 status_is_ok( Sockbuf *sb )
78 {
79         int obr;
80 #ifdef USE_SASL
81         int osr;
82 #endif
83
84         assert( sb != NULL );
85         assert( SOCKBUF_VALID( sb ) );
86
87         obr = sb->sb_buf_ready;
88 #ifdef USE_SASL
89         osr = sb->sb_sec_ready;
90 #endif
91
92    update_status(sb);
93    if (obr!=sb->sb_buf_ready)
94      return 0;
95
96 #ifdef USE_SASL
97    if (osr!=sb->sb_sec_ready)
98      return 0;
99 #endif
100
101    return 1;
102 }
103 #endif
104
105 #ifdef USE_SASL
106 static ber_len_t
107 packet_length( char *buf )
108 {
109    ber_len_t size;
110
111    assert( buf != NULL );
112
113    size = (((ber_len_t)buf[0])<<24)|
114      (((ber_len_t)buf[1])<<16)|
115      (((ber_len_t)buf[2])<<8)|
116      (((ber_len_t)buf[3]));
117    
118    if ((size<0) || (size>MAX_BUF_SIZE)) {
119       /* somebody is trying to mess me up. */
120       lber_log_printf( LDAP_DEBUG_SASL, sb->sb_debug,
121                       "SASL: received packet length of %d bytes\n",
122                       size );      
123       size = 16; /* this should lead to an error. */
124    }
125    
126    return size + 4; /* include the size !!! */
127 }
128 #endif
129
130 static int
131 grow_buffer( Sockbuf_Buf * buf, ber_len_t minsize )
132 {
133    ber_len_t pw;;
134    
135    assert( buf != NULL );
136
137    for( pw=MIN_BUF_SIZE; pw<minsize; pw<<=1 ) {
138       if (pw > MAX_BUF_SIZE) {
139          /* this could mean that somebody is trying to crash us. */
140          return -1;
141       }
142    }
143    minsize = pw;
144
145    if (buf->buf_size<minsize) {
146       if ((buf->buf_base==NULL) || ((buf->buf_end==0) && (buf->buf_ptr==0))) {
147          /* empty buffer */
148          if (buf->buf_base!=NULL)
149            LBER_FREE( buf->buf_base );
150          assert( buf->buf_ptr==0 );
151          assert( buf->buf_end==0 );
152          buf->buf_base = LBER_MALLOC( minsize );
153          if (buf->buf_base==NULL)
154            return -1;
155       } else {
156          char *nb;
157          nb = LBER_REALLOC( buf->buf_base, minsize );
158          if (nb==NULL)
159            return -1;
160          buf->buf_base = nb;
161       }
162       buf->buf_size = minsize;
163    }
164    return 0;
165 }
166
167 #ifdef USE_SASL
168 static ber_slen_t
169 sockbuf_sec_release( Sockbuf *sb, char *buf, ber_len_t len )
170 {
171    /* when this is called:
172     *  sb->sb_sec_buf_in.buf_base  points to a packet.
173     *  sb->sb_sec_buf_in.buf_ptr   contains the total bytes read.
174     *  sb->sb_sec_end.buf_end   contains the packet length.
175     * 
176     *  sb->sb_buf.buf_ptr == sb->sb_buf.buf_end == 0;
177     */
178    long rlen;
179    long total;
180    char *ptr;
181    char *end;
182    long size;
183    
184     assert( buf != NULL );
185         assert( sb != NULL );
186         assert( SOCKBUF_VALID( sb ) );
187
188    assert( sb->sb_sec );
189    assert( sb->sb_sec->sbs_release );
190    assert( sb->sb_sec_buf_in.sb_ptr >= sb->sb_sec_buf_in.sb_end );
191    
192    assert( sb->sb_buf.sb_ptr == 0 );
193    assert( sb->sb_buf.sb_end == 0 );
194
195    assert( status_is_ok(sb) );
196    
197    total = 0;
198    
199    ptr = sb->sb_sec_buf_in.buf_base;
200    end = ptr+ sb->sb_sec_buf_in.buf_ptr;
201    size = sb->sb_sec_buf_in.buf_end;
202    
203    sb->sb_sec_ready = 1;
204    
205    for(;(ptr+size<=end);) {
206       for(;;) {
207          rlen = sb->sb_sec->sbs_release( sb, ptr, size,
208                                         buf, len, 
209                                         sb->sb_buf.buf_base,
210                                         sb->sb_buf.buf_size );
211          if (rlen==0) {
212             /* this means a security violation. */
213             return total; /* total ? total : 0 */
214          }
215          if (rlen<0) {
216             /* this means that the buffer isn't big enough. */
217             if (grow_buffer( &(sb->sb_buf), -rlen )<0)
218               /* memory violation. */
219               return total; /* total ? total : 0 */
220             continue;
221          }
222          /* if (rlen>0) */
223          break;
224       }
225       total+=rlen;
226       
227       /* move to the next packet... */
228       ptr+=size;
229       
230       if (ptr+4<=end)
231         size = packet_length( ptr ); 
232       /* size is always at least 4, so the loop condition is always OK !!*/
233       assert( size>=4 );
234       
235       if (rlen<len) {
236          len-=rlen;
237          buf+=rlen;
238       } else {
239          sb->sb_buf_ready = (sb->sb_buf.buf_end = rlen - len) ? 1 : 0;
240          break;
241       }
242    }
243    
244    if (ptr+size>end)
245      sb->sb_sec_ready = 0;
246    /* clean up the mess. */
247    if (ptr<end) {
248       /* copy back to beginning of buffer. */
249       SAFEMEMCPY( sb->sb_sec_buf_in.buf_base, ptr, end-ptr );
250       sb->sb_sec_buf_in.buf_ptr = 0;
251       sb->sb_sec_buf_in.buf_end -= (ptr - sb->sb_sec_buf_in.buf_base);
252    }
253    assert( status_is_ok(sb) );
254    return total;
255 }
256
257 static long
258 sockbuf_sec_protect( Sockbuf *sb, char *buf, long len )
259 {
260    long ret;
261    long blen;
262    long total;
263    
264    assert( buf != NULL );
265
266    assert( sb != NULL );
267         assert( SOCKBUF_VALID( sb ) );
268
269    assert( sb->sb_sec_out.buf_end == 0 );
270    assert( sb->sb_sec_out.buf_ptr == 0 );
271    
272    assert( sb->sb_sec );
273    assert( sb->sb_sec->sbs_protect );
274    
275    assert( status_is_ok(sb) );
276    
277    total = 0;
278    for(;(len);) {
279       for(;;) {
280          blen = len;
281          ret = sb->sb_sec->sbs_protect( sb, buf, &blen, 
282                                        sb->sb_sec_out.buf_base+
283                                        sb->sb_sec_out.buf_end, 
284                                        sb->sb_sec_out.buf_size -
285                                        sb->sb_sec_out.buf_end );
286          if (ret==0)
287            /* protection error ? */
288            return total;
289          if (ret<0) {
290             if (grow_buffer( &(sb->sb_sec_out),-ret-sb->sb_sec_out.buf_end )<0)
291               /* memory error */
292               return total;
293             continue;
294          }
295          /* else if (ret>0) */
296          break;
297       }
298       sb->sb_sec_out.buf_end += ret;
299       len -= blen;
300       total += blen;
301    }
302    assert( status_is_ok(sb) );
303    return total;
304 }
305 #endif
306
307 static ber_len_t 
308 sockbuf_copy_out( Sockbuf *sb, char **buf, ber_len_t len )
309 {
310    ber_len_t blen = (sb->sb_buf.buf_end - sb->sb_buf.buf_ptr );
311
312    assert( buf != NULL );
313
314    assert( sb != NULL );
315         assert( SOCKBUF_VALID( sb ) );
316    assert( status_is_ok(sb) );
317
318    if (blen) {
319       ber_len_t rlen = (blen<len) ? blen : len;
320       memcpy( *buf, sb->sb_buf.buf_base + sb->sb_buf.buf_ptr, rlen );
321       sb->sb_buf.buf_ptr+=rlen;
322       *buf+=rlen;
323       len -= rlen;
324       if (sb->sb_buf.buf_ptr >= sb->sb_buf.buf_end) {
325          sb->sb_buf.buf_ptr = sb->sb_buf.buf_end = 0;
326          sb->sb_buf_ready = 0;
327       } else {
328          sb->sb_buf_ready = 1;
329       }
330    }
331    assert( status_is_ok(sb) );
332    return len;
333 }
334
335 Sockbuf *ber_sockbuf_alloc( void )
336 {
337         Sockbuf *sb;
338
339         ber_int_options.lbo_valid = LBER_INITIALIZED;
340
341         sb = LBER_CALLOC(1, sizeof(Sockbuf));
342
343         if( sb == NULL ) return NULL;
344
345         ber_pvt_sb_init( sb );
346         return sb;
347 }
348
349 Sockbuf *ber_sockbuf_alloc_fd( ber_socket_t fd )
350 {
351         Sockbuf *sb = ber_sockbuf_alloc();
352
353         if( sb == NULL ) return NULL;
354
355         ber_pvt_sb_set_desc( sb, fd );
356         ber_pvt_sb_set_io( sb, &ber_pvt_sb_io_tcp, NULL );
357         return sb;
358 }
359
360 void ber_sockbuf_free( Sockbuf *sb )
361 {
362         assert(sb != NULL);
363         assert( SOCKBUF_VALID( sb ) );
364         ber_pvt_sb_destroy( sb );
365         LBER_FREE(sb);
366 }
367
368 ber_slen_t 
369 ber_pvt_sb_read( Sockbuf *sb, void *buf_arg, ber_len_t len )
370 {
371    char *buf;
372    ber_slen_t ret;
373    
374    assert( buf_arg != NULL );
375    assert( sb != NULL );
376    assert( SOCKBUF_VALID( sb ) );
377    assert( status_is_ok(sb) );
378
379    /* slapd might have problems with this */
380    assert( ber_pvt_sb_in_use( sb ) );
381
382 #ifdef TEST_PARTIAL_READ
383    if ((rand() & 3)==1) { /* 1 out of 4 */
384       errno = EWOULDBLOCK;
385       return -1;
386    }
387
388    if( len > 0 )
389            len = (rand() % len)+1;
390 #endif   
391    
392    buf = (char *) buf_arg;
393
394    if (sb->sb_buf.buf_ptr!=sb->sb_buf.buf_end) {
395       len = sockbuf_copy_out( sb, &buf, len );
396       if (len==0) {
397          return (buf - (char *) buf_arg);
398       }
399    }
400
401 #ifdef USE_SASL
402    if (sb->sb_sec) {
403       ber_slen_t max;
404       assert( sb->sb_sec->sbs_release );
405       assert( sb->sb_sec_buf_in.buf_base );
406       if (sb->sb_read_ahead) {
407          max = sb->sb_sec_buf_in.buf_size - sb->sb_sec_buf_in.buf_ptr;
408       } else {
409          max = sb->sb_sec_buf_in.buf_end - sb->sb_sec_buf_in.buf_ptr;
410          if (max<=0) {
411             /* special situation. This means that we need to read the first
412              * four bytes for the packet length.
413              */
414             max += 4;
415          }
416       }
417       for(;;) {
418          /* read from stream into sb_sec_buf_in */
419          for(;;) {
420             ret = sockbuf_io_read( sb, sb->sb_sec_buf_in.buf_base +
421                                   sb->sb_sec_buf_in.buf_ptr, max );
422 #ifdef EINTR
423             if ((ret<0) && (errno==EINTR))
424               continue;
425 #endif
426             break;
427          }
428          if (ret<=0) {
429             /* read error. return */
430             goto do_return;
431          }
432          sb->sb_sec_buf_in.buf_ptr += ret;
433          
434          if (sb->sb_sec_buf_in.buf_ptr < sb->sb_sec_buf_in.buf_end) {
435             /* did not finish a packet. give up. */
436             goto do_return;
437          }
438             
439          if (sb->sb_sec_buf_in.buf_end == 0) {
440             /* Were trying to read the first four bytes... */
441             if (sb->sb_sec_buf_in.buf_ptr < 4) {
442                /* did not read enough for packet length. give up. */
443                goto do_return;
444             }
445             /* calculate the packet length. */
446             sb->sb_sec_buf_in.buf_end = 
447                packet_length(sb->sb_sec_buf_in.buf_base );
448             if ((sb->sb_sec_buf_in.buf_end > sb->sb_sec_buf_in.buf_size) &&
449                 (grow_buffer( &(sb->sb_sec_buf_in), sb->sb_sec_buf_in.buf_end)<0)) {
450                /* buffer has to be to big. exit with error. */
451                ret = -1;
452                goto do_return;
453             }
454             if (sb->sb_sec_buf_in.buf_ptr >= sb_sec_buf_in.buf_end) {
455                /* finished packet. decode it. */
456                goto decode_packet;
457             }
458             /* did not finish packet yet. try again ? */
459             if (sb->sb_read_ahead) {
460                /* we were trying to read the max anyway. forget it */
461                goto do_return;
462             }
463          }
464 decode_packet:
465          /* we read enough for at least 1 packet */
466          ret = sockbuf_sec_release( sb, buf, len );
467          if (ret<=0) {
468             /* something went wrong... */
469             goto do_return;
470          }
471          buf+=ret;
472          len-=ret;
473          /* we are finished !!! */
474          if ((len==0) || (ret!=max))
475            goto do_return;
476       }
477    } else {
478 #endif
479       if (sb->sb_read_ahead) {
480          ber_slen_t max;
481          max = sb->sb_buf.buf_size - sb->sb_buf.buf_end;
482          if (max> (ber_slen_t) len) {
483             for(;;) {
484                ret = sockbuf_io_read( sb, 
485                                      sb->sb_buf.buf_base +
486                                      sb->sb_buf.buf_end,
487                                      max );
488 #ifdef EINTR           
489                if ((ret<0) && (errno==EINTR))
490                  continue;
491 #endif
492                break;
493             }
494             if (ret<=0) {
495                /* some error occured */
496                goto do_return;
497             }
498             sb->sb_buf.buf_end += ret;
499             /* move out the data... */
500             len = sockbuf_copy_out( sb, &buf, len );
501             goto do_return;
502          }
503       }
504       /* no read_ahead, just try to put the data in the buf. */
505       for(;;) {
506          ret = sockbuf_io_read( sb, buf, len );
507 #ifdef EINTR     
508          if ((ret<0) && (errno==EINTR))
509            continue;
510 #endif
511          break;
512       }
513       if (ret>0) {
514          buf+=ret;
515          len-=ret;
516       }
517       /* we might as well return, since there is nothing to do... */
518 #ifdef USE_SASL     
519    }
520 #endif
521 do_return:
522    assert( status_is_ok(sb) );
523    if ((ret<=0) && (buf==buf_arg)) {
524       /* there was an error. */
525       return ret;
526    }
527    return (buf - ((char *) buf_arg));
528 }
529
530 #ifdef USE_SASL
531 long sockbuf_do_write( Sockbuf *sb )
532 {
533    long to_go;
534
535    assert( sb != NULL );
536         assert( SOCKBUF_VALID( sb ) );
537
538    to_go = sb->sb_sec_out.buf_end - sb->sb_sec_out.buf_ptr;
539    assert( to_go > 0 );
540    /* there is something left of the last time... */
541    for(;;) {
542       ret = sockbuf_io_write( sb, sb->sb_sec_out.buf_base+
543                              sb->sb_sec_out.buf_ptr, to_go );
544 #ifdef EINTR
545       if ((ret<0) && (errno==EINTR))
546         continue;
547 #endif
548       break;
549    }
550    if (ret<=0) /* error */
551      return ret;
552    sb->sb_sec_out.buf_ptr += ret;
553    if (ret<to_go) /* not enough data, so pretend no data was sent. */
554      return -1;
555    return ret;
556 }
557 #endif
558
559 ber_slen_t ber_pvt_sb_write( Sockbuf *sb, void *buf, ber_len_t len_arg )
560 {
561    ber_slen_t ret;
562    ber_len_t len = len_arg;
563
564         assert( buf != NULL );
565         assert( sb != NULL );
566         assert( SOCKBUF_VALID( sb ) );
567    assert( status_is_ok(sb) );
568
569    /* slapd might have problems with this */
570    assert( ber_pvt_sb_in_use( sb ) );
571
572 #ifdef TEST_PARTIAL_WRITE
573    if ((rand() & 3)==1) { /* 1 out of 4 */
574       errno = EWOULDBLOCK;
575       return -1;
576    }
577
578    len_arg = (rand() % len_arg)+1;
579    len = len_arg;
580 #endif   
581    
582 #ifdef USE_SASL
583    if (sb->sb_sec) {
584       assert( sb->sb_sec_prev_len <= len );
585       if (sb->sb_sec_prev_len) {
586          ret = sockbuf_do_write( sb );
587          if (ret<=0)
588            return ret;
589          /* finished. */
590          len -= sb->sb_sec_prev_len;
591          sb->sb_sec_prev_len = 0;
592          sb->sb_sec_out.buf_end = sb->sb_sec_out.buf_ptr = 0;
593       }
594       /* now protect the next packet. */
595       ret = sockbuf_sec_protect( sb, buf, len );
596       if (ret<=0)
597         return ret;
598       ret = sockbuf_do_write( sb );
599       if (ret<=0) {
600          sb->sb_sec_prev_len = len;
601          return ret;
602       }
603       return len_arg;
604    } else {
605 #endif
606       for(;;) {
607          ret = sockbuf_io_write( sb, buf, len );
608 #ifdef EINTR
609          if ((ret<0) && (errno==EINTR))
610            continue;
611 #endif
612          break;
613       }
614 #ifdef USE_SASL      
615    }
616 #endif
617
618    return ret;
619 }
620      
621 int ber_pvt_sb_close( Sockbuf *sb )
622 {
623    int ret;
624
625    assert( sb != NULL );
626    assert( SOCKBUF_VALID( sb ) );
627    assert( sb->sb_io );
628    assert( sb->sb_io->sbi_close );
629    assert( status_is_ok(sb) );
630    assert( ber_pvt_sb_in_use( sb ) );
631    
632    ret = sb->sb_io->sbi_close( sb );
633    ber_pvt_sb_set_desc( sb, -1 );
634
635    return ret;
636 }
637
638 int ber_pvt_sb_set_readahead( Sockbuf *sb, int rh )
639 {
640    assert( sb != NULL );
641    assert( SOCKBUF_VALID( sb ) );
642    assert( status_is_ok(sb) );
643    sb->sb_read_ahead = (rh!=0);
644    return 0;
645 }
646
647 int ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
648 {
649 #if HAVE_FCNTL
650         int flags = fcntl(ber_pvt_sb_get_desc(sb), F_GETFL);
651         if( nb ) {
652                 flags |= O_NONBLOCK;
653         } else {
654                 flags &= ~O_NONBLOCK;
655         }
656         return fcntl( ber_pvt_sb_get_desc(sb), F_SETFL, flags );
657                 
658 #elif defined( FIONBIO )
659         ioctl_t status = nb ? 1 : 0;
660         return ioctl( sd, FIONBIO, &status );
661 #endif
662 }
663
664 #define USE_NONBLOCK
665 #ifdef USE_NONBLOCK
666 int ber_pvt_sb_set_nonblock( Sockbuf *sb, int nb )
667 {
668    assert( sb != NULL );
669    assert( SOCKBUF_VALID( sb ) );
670    assert( status_is_ok(sb) );
671    if (nb) {
672       sb->sb_non_block = 1;
673 #if 0      
674       sb->sb_read_ahead = 1;
675 #endif
676    } else {
677       sb->sb_non_block = 0;
678 #if 0
679       sb->sb_read_ahead = 0;
680 #endif
681    }
682         if (ber_pvt_sb_in_use(sb)) {
683                 return ber_pvt_socket_set_nonblock(
684                         ber_pvt_sb_get_desc(sb), nb );
685         }
686         return 0;
687 }
688 #endif
689          
690 #define sockbuf_buf_init( bb ) do { \
691                 Sockbuf_Buf *sbb = (bb); \
692                 sbb->buf_base = NULL; \
693                 sbb->buf_ptr = 0; \
694                 sbb->buf_end = 0; \
695                 sbb->buf_size = 0; \
696         } while(0)
697
698 static int 
699 sockbuf_buf_destroy( Sockbuf_Buf *buf )
700 {
701         assert( buf != NULL);
702
703    if (buf->buf_base)
704      LBER_FREE( buf->buf_base );
705    sockbuf_buf_init( buf );
706    return 0;
707 }
708
709 int ber_pvt_sb_init( Sockbuf *sb )
710 {
711         assert( sb != NULL);
712
713         ber_int_options.lbo_valid = LBER_INITIALIZED;
714
715    sb->sb_valid=LBER_VALID_SOCKBUF;
716    sb->sb_options = 0;
717    sb->sb_debug = 0;
718    sb->sb_trans_ready = 0;
719    sb->sb_buf_ready = 0;
720 #ifdef USE_SASL   
721    sb->sb_sec_ready = 0;
722 #endif   
723    sb->sb_read_ahead = 1; /* test */
724    sb->sb_non_block = 0;
725    sb->sb_trans_needs_read = 0;
726    sb->sb_trans_needs_write = 0;
727    sb->sb_fd = -1;
728    sb->sb_iodata = NULL;
729    sb->sb_io = &sb_IO_None;
730    sb->sb_sd = -1;
731 #ifdef DEADWOOD   
732    sb->sb_max_incoming = 0;
733 #endif   
734    sockbuf_buf_init( &(sb->sb_buf) );
735 #ifdef USE_SASL
736    sockbuf_buf_init( &(sb->sb_sec_buf_in) );
737    sockbuf_buf_init( &(sb->sb_sec_buf_out) );
738    sb->sb_sdata = NULL;
739    sb->sb_sec = NULL;
740    sb->sb_sec_prev_len = 0;
741 #endif 
742    
743    assert( SOCKBUF_VALID( sb ) );
744    return 0;
745 }
746    
747 int ber_pvt_sb_destroy( Sockbuf *sb )
748 {
749         assert( sb != NULL);
750         assert( SOCKBUF_VALID(sb) );
751 #ifdef USE_SASL
752    ber_pvt_sb_clear_sec(sb);
753    sockbuf_buf_destroy( &(sb->sb_sec_buf_in) );
754    sockbuf_buf_destroy( &(sb->sb_sec_buf_out) );
755 #endif
756    ber_pvt_sb_clear_io(sb);
757    sockbuf_buf_destroy( &(sb->sb_buf) );
758    return ber_pvt_sb_init( sb );
759 }
760
761 #ifdef USE_SASL
762 int ber_pvt_sb_set_sec( Sockbuf *sb, Sockbuf_Sec * sec, void *arg )
763 {
764    int len;
765         assert( sb != NULL);
766         assert( SOCKBUF_VALID( *sb ) );
767    if ((sb->sb_sec) || (sec==NULL))
768      return -1;
769    
770    sb->sb_sec = sec;
771    
772    if ((sec->sbs_setup) && (sec->sbs_setup( sb, arg)<0)) {
773       return -1;
774    }
775    
776    len = sb->sb_buf.buf_end - sb->sb_buf.buf_ptr;
777    
778    if (len>0) {
779       /* move this to the security layer. */
780       if (grow_buffer( &(sb->sb_sec_buf_in), len )<0)
781         return -1;
782       memcpy( sb->sb_sec_buf_in.buf_base, 
783              sb->sb_buf.buf_base + sb->sb_buf.buf_ptr, len );
784       sb->sb_sec_buf_in.buf_ptr = len;
785       sb->sb_sec_buf_in.buf_end = (len>4) ? packet_length( sb->sb_sec_buf_in ) : 0;
786       sb->sb_buf.buf_ptr = sb->sb_buf.buf_end = 0;
787    }
788    update_status();
789    return 0;
790 }
791
792 int ber_pvt_sb_clear_sec( Sockbuf *sb )
793 {
794         assert( sb != NULL);
795         assert( SOCKBUF_VALID( sb ) );
796
797    if (sb->sb_buf.buf_ptr!=0)
798      return -1;
799    if (sb->sb_sec==NULL)
800      return -1;
801    if ((sb->sb_sec->sbs_remove) && (sb->sb_sec->sbs_remove(sb)<0)) 
802      return -1;
803    
804    sb->sb_sec = NULL;
805    if (sb->sb_sec_buf_in.buf_ptr!=0) {
806       if (grow_buffer( &(sb->sb_buf), 
807                       sb->sb_buf.buf_end + sb->sb_sec_buf_in.buf_ptr)<0)
808         return -1;
809       memcpy( sb->sb_buf.buf_base + sb->sb_buf.buf_end,
810               sb->sb_sec_buf_in.buf_base, sb->sb_sec_buf_in.buf_ptr );
811       sb->sb_buf.buf_end += sb->sb_sec_buf_in.buf_ptr;
812       sb->sb_buf_ready = 1;
813    }
814    sockbuf_buf_destroy( &(sb->sb_sec_buf_in) );
815    assert( sb->sb_sec_buf.buf_end==0 );
816    sockbuf_buf_destroy( &(sb->sb_sec_buf_out) );
817    
818    sb->sb_sec_ready = 0;
819    
820    return 0;
821 }
822 #endif
823
824 int ber_pvt_sb_set_io( Sockbuf *sb, Sockbuf_IO *trans, void *arg )
825 {
826         assert( sb != NULL);
827         assert( SOCKBUF_VALID( sb ) );
828    assert( sb->sb_io == &sb_IO_None );
829
830    if (trans==NULL)
831      return -1;
832    
833    sb->sb_io = trans;
834    
835    if ((trans->sbi_setup) && (trans->sbi_setup( sb, arg)<0))
836      return -1;
837    
838    return 0;
839 }
840
841 int ber_pvt_sb_clear_io( Sockbuf *sb )
842 {
843         assert( sb != NULL);
844         assert( SOCKBUF_VALID( sb ) );
845
846    if (sb->sb_io==&sb_IO_None)
847      return -1;
848    
849    if ((sb->sb_io->sbi_remove) && (sb->sb_io->sbi_remove( sb )<0))
850      return -1;
851
852    sb->sb_io = &sb_IO_None;
853    
854    sb->sb_trans_ready = 0;
855    sb->sb_trans_needs_read = 0;
856    sb->sb_trans_needs_write = 0;
857
858    return 0;
859 }
860
861 /*
862  * Support for TCP
863  */
864
865 static ber_slen_t
866 stream_read( Sockbuf *sb, void *buf, ber_len_t len )
867 {
868         assert( sb != NULL);
869         assert( SOCKBUF_VALID( sb ) );
870
871 #if defined(MACOS)
872 /*
873  * MacTCP/OpenTransport
874  */
875    return tcpread( ber_pvt_sb_get_desc(sb), 0, (unsigned char *)buf, 
876                    len, NULL );
877
878 #elif defined( HAVE_PCNFS ) || \
879    defined( HAVE_WINSOCK ) || defined ( __BEOS__ )
880 /*
881  * PCNFS (under DOS)
882  */
883 /*
884  * Windows Socket API (under DOS/Windows 3.x)
885  */
886 /*
887  * 32-bit Windows Socket API (under Windows NT or Windows 95)
888  */
889    {
890    int rc;
891    rc = recv( ber_pvt_sb_get_desc(sb), buf, len, 0 );
892 #ifdef HAVE_WINSOCK
893    if ( rc < 0 ) errno = WSAGetLastError();
894 #endif
895    return rc;
896    }
897 #elif defined( HAVE_NCSA )
898 /*
899  * NCSA Telnet TCP/IP stack (under DOS)
900  */
901    return nread( ber_pvt_sb_get_desc(sb), buf, len );
902
903 #else
904    return read( ber_pvt_sb_get_desc(sb), buf, len );
905 #endif
906 }
907
908 static ber_slen_t
909 stream_write( Sockbuf *sb, void *buf, ber_len_t len )
910 {
911         assert( sb != NULL);
912         assert( SOCKBUF_VALID( sb ) );
913
914 #if defined(MACOS) 
915 /*
916  * MacTCP/OpenTransport
917  */
918 #define MAX_WRITE       65535
919    return tcpwrite( ber_pvt_sb_get_desc(sb),
920                     (unsigned char *)(buf), 
921                     (len<MAX_WRITE)? len : MAX_WRITE );
922
923 #elif defined( HAVE_PCNFS) \
924    || defined( HAVE_WINSOCK) || defined ( __BEOS__ )
925 /*
926  * PCNFS (under DOS)
927  */
928 /*
929  * Windows Socket API (under DOS/Windows 3.x)
930  */
931 /*
932  * 32-bit Windows Socket API (under Windows NT or Windows 95)
933  */
934
935    {
936    int rc;
937    rc = send( ber_pvt_sb_get_desc(sb), buf, len, 0 );
938 #ifdef HAVE_WINSOCK
939    if ( rc < 0 ) errno = WSAGetLastError();
940 #endif
941    return rc;
942    }
943
944 #elif defined(HAVE_NCSA)
945    return netwrite( ber_pvt_sb_get_desc(sb), buf, len );
946
947 #elif defined(VMS)
948 /*
949  * VMS -- each write must be 64K or smaller
950  */
951 #define MAX_WRITE 65535
952    return write( ber_pvt_sb_get_desc(sb), buf, 
953                  (len<MAX_WRITE)? len : MAX_WRITE);
954 #else
955    return write( ber_pvt_sb_get_desc(sb), buf, len );
956 #endif   
957 }   
958    
959 static int 
960 stream_close( Sockbuf *sb )
961 {
962         assert( sb != NULL);
963         assert( SOCKBUF_VALID( sb ) );
964    tcp_close( ber_pvt_sb_get_desc( sb ) );
965    return 0;
966 }
967
968 Sockbuf_IO ber_pvt_sb_io_tcp=
969 {
970         NULL,   /* sbi_setup */
971         NULL,   /* sbi_release */
972         stream_read,    /* sbi_read */
973         stream_write,   /* sbi_write */
974         stream_close,   /* sbi_close */
975 };
976
977 /*
978  * Support for UDP (CLDAP)
979  */
980
981 struct dgram_data
982 {
983         struct sockaddr dst;
984         struct sockaddr src;
985 };
986
987 static int 
988 dgram_setup( Sockbuf *sb, void *arg )
989 {
990         assert( sb != NULL);
991         assert( SOCKBUF_VALID( sb ) );
992
993    sb->sb_iodata = LBER_MALLOC( sizeof( struct dgram_data ) );
994    if (sb->sb_iodata==NULL)
995      return -1;
996    sb->sb_read_ahead = 1; /* important since udp is packet based. */
997    return 0;
998 }
999
1000 static int 
1001 dgram_release( Sockbuf *sb )
1002 {
1003         assert( sb != NULL);
1004         assert( SOCKBUF_VALID( sb ) );
1005
1006    LBER_FREE( sb->sb_iodata );
1007    return 0;
1008 }
1009
1010 static ber_slen_t
1011 dgram_read( Sockbuf *sb, void *buf, ber_len_t len )
1012 {
1013 #ifdef LDAP_CONNECTIONLESS
1014    ber_slen_t rc;
1015    socklen_t  addrlen;
1016    struct dgram_data *dd;
1017    
1018         assert( sb != NULL );
1019         assert( SOCKBUF_VALID( sb ) );
1020         assert( buf != NULL );
1021
1022    dd = (struct dgram_data *)(sb->sb_iodata);
1023    
1024    addrlen = sizeof( struct sockaddr );
1025    rc=recvfrom( ber_pvt_sb_get_desc(sb), buf, len, 0, &(dd->src), &addrlen );
1026    
1027    if ( sb->sb_debug ) {
1028       ber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug,
1029                       "dgram_read udp_read %ld bytes\n",
1030                       (long) rc );
1031       if ( rc > 0 )
1032         ber_log_bprint( LDAP_DEBUG_PACKETS, sb->sb_debug,
1033                         buf, rc );
1034    }
1035    return rc;
1036 # else /* LDAP_CONNECTIONLESS */
1037    return -1;
1038 # endif /* LDAP_CONNECTIONLESS */
1039 }
1040
1041 static ber_slen_t 
1042 dgram_write( Sockbuf *sb, void *buf, ber_len_t len )
1043 {
1044 #ifdef LDAP_CONNECTIONLESS
1045    ber_slen_t rc;
1046    struct dgram_data *dd;
1047    
1048         assert( sb != NULL );
1049         assert( SOCKBUF_VALID( sb ) );
1050         assert( buf != NULL );
1051
1052    dd = (struct dgram_data *)(sb->sb_iodata);
1053    
1054    rc=sendto( ber_pvt_sb_get_desc(sb), buf, len, 0, &(dd->dst),
1055              sizeof( struct sockaddr ) );
1056
1057    if ( rc <= 0 )
1058        return( -1 );
1059    
1060    /* fake error if write was not atomic */
1061    if (rc < len) {
1062 # ifdef EMSGSIZE
1063       errno = EMSGSIZE;
1064 # endif
1065       return( -1 );
1066    }
1067    return rc;
1068 #else
1069    return -1;
1070 #endif  
1071 }
1072
1073 static int 
1074 dgram_close( Sockbuf *sb )
1075 {
1076         assert( sb != NULL );
1077         assert( SOCKBUF_VALID( sb ) );
1078
1079         tcp_close( ber_pvt_sb_get_desc(sb) );
1080         return 0;
1081 }
1082
1083 Sockbuf_IO ber_pvt_sb_io_udp=
1084 {
1085         dgram_setup,    /* sbi_setup */
1086         dgram_release,  /* sbi_release */
1087         dgram_read,     /* sbi_read */
1088         dgram_write,    /* sbi_write */
1089         dgram_close,    /* sbi_close */
1090 };
1091
1092 int ber_pvt_sb_udp_set_dst(Sockbuf *sb, void *addr )
1093 {
1094    struct dgram_data *dd;
1095         assert( sb != NULL );
1096         assert( SOCKBUF_VALID( sb ) );
1097    assert( sb->sb_io == &ber_pvt_sb_io_udp );
1098    dd = (struct dgram_data *) (sb->sb_iodata);
1099    memcpy( &(dd->dst), addr, sizeof( struct sockaddr ) );
1100    return 0;
1101 }
1102
1103 void *ber_pvt_sb_udp_get_src( Sockbuf *sb )
1104 {
1105    struct dgram_data *dd;
1106
1107         assert( sb != NULL );
1108         assert( SOCKBUF_VALID( sb ) );
1109    assert( sb->sb_io == &ber_pvt_sb_io_udp );
1110    dd = (struct dgram_data *) (sb->sb_iodata);
1111    return &(dd->src);
1112 }
1113
1114 /*
1115  * debug routines.
1116  * 
1117  * BUGS:
1118  * These routines should really call abort, but at the moment that would
1119  * break the servers.
1120  */
1121
1122 static ber_slen_t
1123 have_no_read( Sockbuf *sb, void *buf, ber_len_t len )
1124 {
1125         assert( sb != NULL );
1126         assert( SOCKBUF_VALID( sb ) );
1127
1128    ber_log_printf( LDAP_DEBUG_ANY, ber_int_debug,
1129                    "warning: reading from uninitialized sockbuf\n");
1130    errno =  EBADF;
1131    return -1;
1132 }
1133
1134 static ber_slen_t
1135 have_no_write( Sockbuf *sb, void *buf, ber_len_t len )
1136 {
1137         assert( sb != NULL );
1138         assert( SOCKBUF_VALID( sb ) );
1139
1140    ber_log_printf( LDAP_DEBUG_ANY, ber_int_debug,
1141                    "warning: writing to uninitialized sockbuf\n");
1142    errno =  EBADF;
1143    return -1;
1144 }
1145
1146 static int 
1147 have_no_close( Sockbuf *sb )
1148 {   
1149         assert( sb != NULL );
1150         assert( SOCKBUF_VALID( sb ) );
1151
1152    assert( 0 );
1153    return -1;
1154 }