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