From 7e7db2578d1f323d91ba92482988242ecb8b5c86 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Wed, 5 Mar 2003 01:35:39 +0000 Subject: [PATCH] Added ldap_pvt_get_hname. Use instead of ldap_pvt_gethostbyaddr_a when all you want is the hostname. Supports IPv6 addresses. --- libraries/libldap/os-ip.c | 50 +++++++-------- libraries/libldap/util-int.c | 120 ++++++++++++++++++++++++++++++++++- 2 files changed, 141 insertions(+), 29 deletions(-) diff --git a/libraries/libldap/os-ip.c b/libraries/libldap/os-ip.c index fc705e9f33..738e97f930 100644 --- a/libraries/libldap/os-ip.c +++ b/libraries/libldap/os-ip.c @@ -499,7 +499,6 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, char * ldap_host_connected_to( Sockbuf *sb ) { - struct hostent *hp; socklen_t len; #ifdef LDAP_PF_INET6 struct sockaddr_storage sabuf; @@ -507,13 +506,9 @@ ldap_host_connected_to( Sockbuf *sb ) struct sockaddr sabuf; #endif struct sockaddr *sa = (struct sockaddr *) &sabuf; - char *addr; - char *host; - - /* buffers for gethostbyaddr_r */ - struct hostent he_buf; - int local_h_errno; - char *ha_buf=NULL; + char *host = NULL, *herr; + char hbuf[NI_MAXHOST]; + int rc; ber_socket_t sd; (void)memset( (char *)sa, '\0', sizeof sabuf ); @@ -537,31 +532,32 @@ ldap_host_connected_to( Sockbuf *sb ) #endif #ifdef LDAP_PF_INET6 case AF_INET6: - addr = (char *) &((struct sockaddr_in6 *)sa)->sin6_addr; - len = sizeof( struct in6_addr ); + { + struct in6_addr localhost = IN6ADDR_LOOPBACK_INIT; + if( memcmp ( &((struct sockaddr_in6 *)sa)->sin6_addr, + &localhost, sizeof(localhost)) == 0 ) + { + return LDAP_STRDUP( ldap_int_hostname ); + } + } break; #endif case AF_INET: - addr = (char *) &((struct sockaddr_in *)sa)->sin_addr; - len = sizeof( struct in_addr ); - { - struct sockaddr_in localhost; - localhost.sin_addr.s_addr = htonl( INADDR_ANY ); + struct in_addr localhost; + localhost.s_addr = htonl( INADDR_ANY ); - if( memcmp ( &localhost.sin_addr, - &((struct sockaddr_in *)sa)->sin_addr, - sizeof(localhost.sin_addr) ) == 0 ) + if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr, + &localhost, sizeof(localhost) ) == 0 ) { return LDAP_STRDUP( ldap_int_hostname ); } #ifdef INADDR_LOOPBACK - localhost.sin_addr.s_addr = htonl( INADDR_LOOPBACK ); + localhost.s_addr = htonl( INADDR_LOOPBACK ); - if( memcmp ( &localhost.sin_addr, - &((struct sockaddr_in *)sa)->sin_addr, - sizeof(localhost.sin_addr) ) == 0 ) + if( memcmp ( &((struct sockaddr_in *)sa)->sin_addr, + &localhost, sizeof(localhost) ) == 0 ) { return LDAP_STRDUP( ldap_int_hostname ); } @@ -574,15 +570,13 @@ ldap_host_connected_to( Sockbuf *sb ) break; } - host = NULL; - if ((ldap_pvt_gethostbyaddr_a( addr, len, sa->sa_family, - &he_buf, &ha_buf, &hp, &local_h_errno ) == 0 ) && - (hp != NULL) && ( hp->h_name != NULL ) ) + hbuf[0] = 0; + if (ldap_pvt_get_hname( sa, len, hbuf, sizeof(hbuf), &herr ) == 0 && + hbuf[0] ) { - host = LDAP_STRDUP( hp->h_name ); + host = LDAP_STRDUP( hbuf ); } - LDAP_FREE( ha_buf ); return host; } #endif diff --git a/libraries/libldap/util-int.c b/libraries/libldap/util-int.c index 59c3db4815..6d5886d365 100644 --- a/libraries/libldap/util-int.c +++ b/libraries/libldap/util-int.c @@ -178,7 +178,125 @@ int ldap_pvt_gethostbyname_a( return -1; #endif } - + +#ifndef GETNAMEINFO +static const char * +hp_strerror( int err ) +{ + switch (err) { + case HOST_NOT_FOUND: return "Host not found (authoritative)"; + case TRY_AGAIN: return "Host not found (server fail?)"; + case NO_RECOVERY: return "Non-recoverable failure"; + case NO_DATA: return "No data of requested type"; +#ifdef NETDB_INTERNAL + case NETDB_INTERNAL: return STRERROR( errno ); +#endif + default: break; + } + return "Unknown resolver error"; +} +#endif + +int ldap_pvt_get_hname( + const struct sockaddr *sa, + int len, + char *name, + int namelen, + char **err ) +{ + int rc; +#if defined( HAVE_GETNAMEINFO ) + +#if defined( LDAP_R_COMPILE ) + ldap_pvt_thread_mutex_lock( &ldap_int_resolv_mutex ); +#endif + rc = getnameinfo( sa, len, name, namelen, NULL, 0, 0 ); +#if defined( LDAP_R_COMPILE ) + ldap_pvt_thread_mutex_unlock( &ldap_int_resolv_mutex ); +#endif + if ( rc ) *err = AC_GAI_STRERROR( rc ); + return rc; + +#else /* !HAVE_GETNAMEINFO */ + char *addr; + int alen; + struct hostent *hp = NULL; +#ifdef HAVE_GETHOSTBYADDR_R + struct hostent hb; + int buflen=BUFSTART, h_errno; + char *buf=NULL; +#endif + +#ifdef LDAP_PF_INET6 + if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa; + addr = (char *)&sin->sin6_addr; + alen = sizeof(sin->sin6_addr); + } else +#endif + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + addr = (char *)&sin->sin_addr; + alen = sizeof(sin->sin_addr); + } else { + rc = NO_RECOVERY; + *err = hp_strerror( rc ); + return rc; + } +#if defined( HAVE_GETHOSTBYADDR_R ) + for(;buflensa_family, + &hb, buf, buflen, &h_errno ); + rc = (hp == NULL) ? -1 : 0; +#else + rc = gethostbyaddr_r( addr, alen, sa->sa_family, + &hb, buf, buflen, + &hp, &h_errno ); +#endif +#ifdef NETDB_INTERNAL + if ((rc<0) && + (h_errno==NETDB_INTERNAL) && + (errno==ERANGE)) + { + buflen*=2; + continue; + } +#endif + break; + } + if (hp) { + strncpy( name, hp->h_name, namelen ); + } else { + *err = hp_strerror( h_errno ); + } + LDAP_FREE(buf); +#else /* HAVE_GETHOSTBYADDR_R */ + +#if defined( LDAP_R_COMPILE ) + ldap_pvt_thread_mutex_lock( &ldap_int_resolv_mutex ); +#endif + hp = gethostbyaddr( addr, alen, sa->sa_family ); + if (hp) { + strncpy( name, hp->h_name, namelen ); + rc = 0; + } else { + rc = h_errno; + *err = hp_strerror( h_errno ); + } +#if defined( LDAP_R_COMPILE ) + ldap_pvt_thread_mutex_unlock( &ldap_int_resolv_mutex ); +#endif + +#endif /* !HAVE_GETHOSTBYADDR_R */ + return rc; +#endif /* !HAVE_GETNAMEINFO */ +} + int ldap_pvt_gethostbyaddr_a( const char *addr, int len, -- 2.39.5