]> git.sur5r.net Git - openldap/blobdiff - libraries/libldap/os-ip.c
Removed numerous memory leaks detected by Mark Meredith.
[openldap] / libraries / libldap / os-ip.c
index cc358ceefc1803e19e1ebb924eaea38023aecdef..b17e71a58fd78657f56154c5ff8152dd75ce43c2 100644 (file)
 /*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*  Portions
  *  Copyright (c) 1995 Regents of the University of Michigan.
  *  All rights reserved.
  *
  *  os-ip.c -- platform-specific TCP & UDP related code
  */
 
-#ifndef lint 
-static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University of Michigan.\nAll rights reserved.\n";
-#endif
+#include "portable.h"
 
 #include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
 
-#ifdef _WIN32
-#include <io.h>
-#include "msdos.h"
-#else /* _WIN32 */
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <unistd.h>
-#endif /* _WIN32 */
-#ifdef _AIX
-#include <sys/select.h>
-#endif /* _AIX */
-#ifdef VMS
-#include "ucx_select.h"
-#endif /* VMS */
+#include <ac/stdlib.h>
 
-#include "portable.h"
-#include "lber.h"
-#include "ldap.h"
+#include <ac/errno.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/unistd.h>
 
-#ifdef LDAP_REFERRALS
-#ifdef USE_SYSCONF
-#include <unistd.h>
-#endif /* USE_SYSCONF */
-#ifdef notyet
-#ifdef NEED_FILIO
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif /* HAVE_IO_H */
+
+#if defined( HAVE_SYS_FILIO_H )
 #include <sys/filio.h>
-#else /* NEED_FILIO */
+#elif defined( HAVE_SYS_IOCTL_H )
 #include <sys/ioctl.h>
-#endif /* NEED_FILIO */
-#endif /* notyet */
-#endif /* LDAP_REFERRALS */
-
-#ifdef MACOS
-#define tcp_close( s )         tcpclose( s )
-#else /* MACOS */
-#ifdef DOS
-#ifdef PCNFS
-#define tcp_close( s )         close( s )
-#endif /* PCNFS */
-#ifdef NCSA
-#define tcp_close( s )         netclose( s ); netshut()
-#endif /* NCSA */
-#ifdef WINSOCK
-#define tcp_close( s )         closesocket( s ); WSACleanup();
-#endif /* WINSOCK */
-#else /* DOS */
-#define tcp_close( s )         close( s )
-#endif /* DOS */
-#endif /* MACOS */
+#endif
 
 #include "ldap-int.h"
 
 int
-ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address,
+ldap_connect_to_host( Sockbuf *sb, const char *host, unsigned long address,
        int port, int async )
 /*
  * if host == NULL, connect using address
  * "address" and "port" must be in network byte order
  * zero is returned upon success, -1 if fatal error, -2 EINPROGRESS
- * async is only used ifdef LDAP_REFERRALS (non-0 means don't wait for connect)
+ * async is only used ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS (non-0 means don't wait for connect)
  * XXX async is not used yet!
  */
 {
-       int                     rc, i, s = 0;
+       int                     rc, i;
+       ber_socket_t s = AC_SOCKET_INVALID;
        int                     connected, use_hp;
        struct sockaddr_in      sin;
        struct hostent          *hp = NULL;
 #ifdef notyet
-#ifdef LDAP_REFERRALS
-       int                     status; /* for ioctl call */
-#endif /* LDAP_REFERRALS */
+       ioctl_t                 status; /* for ioctl call */
 #endif /* notyet */
-
+   
+       /* buffers for ldap_pvt_gethostbyname_a */
+       struct hostent          he_buf;
+       int                     local_h_errno;
+       char                    *ha_buf=NULL;
+#define DO_RETURN(x) if (ha_buf) LDAP_FREE(ha_buf); return (x);
+   
        Debug( LDAP_DEBUG_TRACE, "ldap_connect_to_host: %s:%d\n",
-           ( host == NULL ) ? "(by address)" : host, ntohs( port ), 0 );
+           ( host == NULL ) ? "(by address)" : host, (int) ntohs( (short) port ), 0 );
 
        connected = use_hp = 0;
 
-       if ( host != NULL && ( address = inet_addr( host )) == -1 ) {
-               if ( (hp = gethostbyname( host )) == NULL ) {
+       if ( host != NULL ) {
+           address = inet_addr( host );
+           /* This was just a test for -1 until OSF1 let inet_addr return
+              unsigned int, which is narrower than 'unsigned long address' */
+           if ( address == 0xffffffff || address == (unsigned long) -1 ) {
+               if ( ( ldap_pvt_gethostbyname_a( host, &he_buf, &ha_buf,
+                       &hp, &local_h_errno) < 0) || (hp==NULL))
+               {
+#ifdef HAVE_WINSOCK
+                       errno = WSAGetLastError();
+#else
                        errno = EHOSTUNREACH;   /* not exactly right, but... */
-                       return( -1 );
+#endif
+                       DO_RETURN( -1 );
                }
                use_hp = 1;
+           }
        }
 
        rc = -1;
        for ( i = 0; !use_hp || ( hp->h_addr_list[ i ] != 0 ); i++ ) {
                if (( s = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
-                       return( -1 );
+                       DO_RETURN( -1 );
                }
 #ifdef notyet
-#ifdef LDAP_REFERRALS
                status = 1;
                if ( async && ioctl( s, FIONBIO, (caddr_t)&status ) == -1 ) {
                        Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
                            s, 0, 0 );
                }
-#endif /* LDAP_REFERRALS */
 #endif /* notyet */
                (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
                sin.sin_family = AF_INET;
@@ -131,8 +108,10 @@ ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address,
                        rc = 0;
                        break;
                } else {
+#ifdef HAVE_WINSOCK
+                       errno = WSAGetLastError();
+#endif
 #ifdef notyet
-#ifdef LDAP_REFERRALS
 #ifdef EAGAIN
                        if ( errno == EINPROGRESS || errno == EAGAIN ) {
 #else /* EAGAIN */
@@ -143,7 +122,6 @@ ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address,
                                rc = -2;
                                break;
                        }
-#endif /* LDAP_REFERRALS */
 #endif /* notyet */
 
 #ifdef LDAP_DEBUG              
@@ -151,42 +129,43 @@ ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address,
                                perror( (char *)inet_ntoa( sin.sin_addr ));
                        }
 #endif
-                       close( s );
+                       tcp_close( s );
                        if ( !use_hp ) {
                                break;
                        }
                }
        }
 
-       sb->sb_sd = s;
+       ber_pvt_sb_set_desc( sb, s );           
 
        if ( connected ) {
+          
 #ifdef notyet
-#ifdef LDAP_REFERRALS
                status = 0;
                if ( !async && ioctl( s, FIONBIO, (caddr_t)&on ) == -1 ) {
                        Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
                            s, 0, 0 );
                }
-#endif /* LDAP_REFERRALS */
 #endif /* notyet */
 
                Debug( LDAP_DEBUG_TRACE, "sd %d connected to: %s\n",
-                   s, inet_ntoa( sin.sin_addr ), 0 );
+                   s, (char *) inet_ntoa( sin.sin_addr ), 0 );
        }
 
-       return( rc );
+       DO_RETURN( rc );
 }
+   
+#undef DO_RETURN
 
 
 void
 ldap_close_connection( Sockbuf *sb )
 {
-    tcp_close( sb->sb_sd );
+       ber_pvt_sb_close( sb );
 }
 
 
-#ifdef KERBEROS
+#if defined( HAVE_KERBEROS ) || defined( HAVE_TLS )
 char *
 ldap_host_connected_to( Sockbuf *sb )
 {
@@ -195,9 +174,16 @@ ldap_host_connected_to( Sockbuf *sb )
        int                     len;
        struct sockaddr_in      sin;
 
+       /* buffers for gethostbyaddr_r */
+       struct hostent          he_buf;
+        int                    local_h_errno;
+       char                    *ha_buf=NULL;
+#define DO_RETURN(x) if (ha_buf) LDAP_FREE(ha_buf); return (x);
+   
        (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
        len = sizeof( sin );
-       if ( getpeername( sb->sb_sd, (struct sockaddr *)&sin, &len ) == -1 ) {
+
+       if ( getpeername( ber_pvt_sb_get_desc(sb), (struct sockaddr *)&sin, &len ) == -1 ) {
                return( NULL );
        }
 
@@ -206,19 +192,24 @@ ldap_host_connected_to( Sockbuf *sb )
         * this is necessary for kerberos to work right, since the official
         * hostname is used as the kerberos instance.
         */
-       if (( hp = gethostbyaddr( (char *) &sin.sin_addr,
-           sizeof( sin.sin_addr ), AF_INET )) != NULL ) {
+       if ((ldap_pvt_gethostbyaddr_a( (char *) &sin.sin_addr,
+               sizeof( sin.sin_addr ), 
+               AF_INET, &he_buf, &ha_buf,
+               &hp,&local_h_errno ) ==0 ) && (hp != NULL) )
+       {
                if ( hp->h_name != NULL ) {
-                       return( strdup( hp->h_name ));
+                       char *host = LDAP_STRDUP( hp->h_name );   
+                       DO_RETURN( host );
                }
        }
 
-       return( NULL );
+       DO_RETURN( NULL );
 }
-#endif /* KERBEROS */
+#undef DO_RETURN   
+   
+#endif /* HAVE_KERBEROS || HAVE_TLS */
 
 
-#ifdef LDAP_REFERRALS
 /* for UNIX */
 struct selectinfo {
        fd_set  si_readfds;
@@ -234,9 +225,9 @@ ldap_mark_select_write( LDAP *ld, Sockbuf *sb )
        struct selectinfo       *sip;
 
        sip = (struct selectinfo *)ld->ld_selectinfo;
-
-       if ( !FD_ISSET( sb->sb_sd, &sip->si_writefds )) {
-               FD_SET( sb->sb_sd, &sip->si_writefds );
+       
+       if ( !FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_writefds )) {
+               FD_SET( (u_int) sb->sb_sd, &sip->si_writefds );
        }
 }
 
@@ -248,8 +239,8 @@ ldap_mark_select_read( LDAP *ld, Sockbuf *sb )
 
        sip = (struct selectinfo *)ld->ld_selectinfo;
 
-       if ( !FD_ISSET( sb->sb_sd, &sip->si_readfds )) {
-               FD_SET( sb->sb_sd, &sip->si_readfds );
+       if ( !FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_readfds )) {
+               FD_SET( (u_int) sb->sb_sd, &sip->si_readfds );
        }
 }
 
@@ -261,8 +252,8 @@ ldap_mark_select_clear( LDAP *ld, Sockbuf *sb )
 
        sip = (struct selectinfo *)ld->ld_selectinfo;
 
-       FD_CLR( sb->sb_sd, &sip->si_writefds );
-       FD_CLR( sb->sb_sd, &sip->si_readfds );
+       FD_CLR( (u_int) ber_pvt_sb_get_desc(sb), &sip->si_writefds );
+       FD_CLR( (u_int) ber_pvt_sb_get_desc(sb), &sip->si_readfds );
 }
 
 
@@ -273,7 +264,7 @@ ldap_is_write_ready( LDAP *ld, Sockbuf *sb )
 
        sip = (struct selectinfo *)ld->ld_selectinfo;
 
-       return( FD_ISSET( sb->sb_sd, &sip->si_use_writefds ));
+       return( FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_use_writefds ));
 }
 
 
@@ -284,16 +275,16 @@ ldap_is_read_ready( LDAP *ld, Sockbuf *sb )
 
        sip = (struct selectinfo *)ld->ld_selectinfo;
 
-       return( FD_ISSET( sb->sb_sd, &sip->si_use_readfds ));
+       return( FD_ISSET( ber_pvt_sb_get_desc(sb), &sip->si_use_readfds ));
 }
 
 
 void *
-ldap_new_select_info()
+ldap_new_select_info( void )
 {
        struct selectinfo       *sip;
 
-       if (( sip = (struct selectinfo *)calloc( 1,
+       if (( sip = (struct selectinfo *)LDAP_CALLOC( 1,
            sizeof( struct selectinfo ))) != NULL ) {
                FD_ZERO( &sip->si_readfds );
                FD_ZERO( &sip->si_writefds );
@@ -306,7 +297,7 @@ ldap_new_select_info()
 void
 ldap_free_select_info( void *sip )
 {
-       free( sip );
+       LDAP_FREE( sip );
 }
 
 
@@ -319,10 +310,12 @@ do_ldap_select( LDAP *ld, struct timeval *timeout )
        Debug( LDAP_DEBUG_TRACE, "do_ldap_select\n", 0, 0, 0 );
 
        if ( tblsize == 0 ) {
-#ifdef USE_SYSCONF
+#if defined( HAVE_SYSCONF )
                tblsize = sysconf( _SC_OPEN_MAX );
-#else /* !USE_SYSCONF */
+#elif defined( HAVE_GETDTABLESIZE )
                tblsize = getdtablesize();
+#else
+               tblsize = FD_SETSIZE;
 #endif /* !USE_SYSCONF */
 
 #ifdef FD_SETSIZE
@@ -339,4 +332,3 @@ do_ldap_select( LDAP *ld, struct timeval *timeout )
        return( select( tblsize, &sip->si_use_readfds, &sip->si_use_writefds,
            NULL, timeout ));
 }
-#endif /* LDAP_REFERRALS */