/* * Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of Michigan at Ann Arbor. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ #include "portable.h" #include #include #include #include #include #include #include #include /* get dap_unbind() */ #if ISODEPACKAGE == IC #include #else #include #endif #include "lber.h" #include "ldap.h" #include "common.h" #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_SYS_FILIO_H #include #endif #ifdef __hpux #define FIOGETOWN FIOGSAIOOWN #endif struct conn *conns; struct conn * conn_dup( struct conn *cn ) { struct conn *new; if ( (new = (struct conn *) malloc( sizeof(struct conn) )) == NULL ) return( NULL ); *new = *cn; new->c_next = NULL; new->c_time = 0L; new->c_paddr = psap_cpy( cn->c_paddr ); new->c_dn = strdup( cn->c_dn ); if ( new->c_credlen > 0 ) { new->c_cred = (char *) malloc( cn->c_credlen ); SAFEMEMCPY( new->c_cred, cn->c_cred, cn->c_credlen ); } else { new->c_cred = ""; } new->c_credlen = cn->c_credlen; new->c_refcnt = 1; return( new ); } int conn_init( void ) { struct PSAPaddr *addr; if ( (conns = (struct conn *) malloc( sizeof(struct conn) )) == NULL ) { Debug( LDAP_DEBUG_ANY, "conn_init: malloc failed\n", 0, 0, 0 ); return( -1 ); } conns->c_ad = -1; conns->c_dn = NULL; conns->c_cred = NULL; conns->c_credlen = 0; if ( dsa_address == NULL || (addr = str2paddr( dsa_address )) == NULLPA ) { conns->c_paddr = NULLPA; Debug( LDAP_DEBUG_ANY, "conn_init: bad DSA address (%s)\n", dsa_address ? dsa_address : "NULL", 0, 0 ); } else { conns->c_paddr = psap_cpy( addr ); } conns->c_refcnt = 1; /* this conn is never deleted */ conns->c_next = NULL; return( 0 ); } void conn_free( struct conn *conn ) { struct timeval tv; Debug( LDAP_DEBUG_TRACE, "conn_free (%s): refcnt is %d\n", paddr2str( conn->c_paddr, NULLNA ), conn->c_refcnt, 0 ); if ( --conn->c_refcnt > 0 ) return; gettimeofday( &tv, (struct timezone *)NULL ); if ( conn->c_time != 0L && (tv.tv_sec - conn->c_time) < referral_connection_timeout ) { Debug( LDAP_DEBUG_TRACE, "conn_free: referral conn ttl is %d\n", referral_connection_timeout - (tv.tv_sec - conn->c_time), 0, 0 ); return; } conn_del( conn ); if ( conn->c_paddr ) free( (char *) conn->c_paddr ); if ( conn->c_dn ) free( conn->c_dn ); if ( conn->c_credlen > 0 ) free( conn->c_cred ); free( conn ); } void conn_del( struct conn *conn ) { struct conn *tmp, *prev; Debug( LDAP_DEBUG_TRACE, "conn_del (%s)\n", paddr2str( conn->c_paddr, NULLNA ), 0, 0 ); prev = NULL; for ( tmp = conns; tmp != NULL; tmp = tmp->c_next ) { if ( tmp == conn ) break; prev = tmp; } if ( tmp == NULL ) { Debug( LDAP_DEBUG_ANY, "conn_del: cannot find conn\n", 0, 0, 0 ); return; } if ( prev == NULL ) { conns = conns->c_next; /* delete head of list */ } else { prev->c_next = tmp->c_next; } } void conn_setfds( fd_set *fds ) { struct conn *tmp; for ( tmp = conns; tmp != NULL; tmp = tmp->c_next ) { if ( tmp->c_ad != -1 ) FD_SET( tmp->c_ad, fds ); } } void conn_badfds( void ) { struct conn *tmp; for ( tmp = conns; tmp != NULL; tmp = tmp->c_next ) { if ( isclosed( tmp->c_ad ) ) { Debug( LDAP_DEBUG_ANY, "conn_badfds: fd %d is bad\n", tmp->c_ad, 0, 0 ); tmp->c_ad = -1; } } } struct conn * conn_getfd( fd_set *fds ) { struct conn *tmp; for ( tmp = conns; tmp != NULL; tmp = tmp->c_next ) { if ( tmp->c_ad != -1 ) if ( FD_ISSET( tmp->c_ad, fds ) ) return( tmp ); } return( NULL ); } void conn_add( struct conn *new ) { struct timeval tv; #ifdef LDAP_DEBUG if ( ldap_debug & LDAP_DEBUG_CONNS ) { char *str; str = paddr2str( new->c_paddr, NULLNA ); Debug( LDAP_DEBUG_CONNS, "conn_add: (%s)\n", str, 0, 0 ); } #endif gettimeofday( &tv, (struct timezone *)NULL ); new->c_time = tv.tv_sec; new->c_next = conns; new->c_refcnt = 1; conns = new; } static int psap_cmp( struct PSAPaddr *a, struct PSAPaddr *b ) { return( bcmp( (char *) a, (char *) b, sizeof(struct PSAPaddr) ) ); } struct conn * conn_find( struct conn *c ) { struct conn *tmp; #ifdef LDAP_DEBUG if ( ldap_debug & LDAP_DEBUG_CONNS ) { char *str; str = paddr2str( c->c_paddr, NULLNA ); Debug( LDAP_DEBUG_CONNS, "conn_find: (%s)\n", str, 0, 0 ); } #endif for ( tmp = conns; tmp != NULL; tmp = tmp->c_next ) { #ifdef LDAP_DEBUG if ( ldap_debug & LDAP_DEBUG_CONNS ) { char *str; str = paddr2str( tmp->c_paddr, NULLNA ); Debug( LDAP_DEBUG_CONNS, "conn_find: compare to (%s)\n", str, 0, 0 ); } #endif if ( psap_cmp( tmp->c_paddr, c->c_paddr ) == 0 && strcmp( tmp->c_dn, c->c_dn ) == 0 && tmp->c_credlen == c->c_credlen && bcmp( tmp->c_cred, c->c_cred, c->c_credlen ) == 0 ) { Debug( LDAP_DEBUG_CONNS, "conn_find: found\n", 0, 0, 0 ); return( tmp ); } } Debug( LDAP_DEBUG_CONNS, "conn_find: not found\n", 0, 0, 0 ); return( NULL ); } void conn_close( void ) { struct conn *tmp; for ( tmp = conns; tmp != NULL; tmp = tmp->c_next ) { if ( tmp->c_ad != -1 ) dap_unbind( tmp->c_ad ); } } int isclosed( int ad ) { int o; if ( ioctl( ad, FIOGETOWN, &o ) < 0 ) return( errno == EBADF ? 1 : 0 ); else return( 0 ); }