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 = (char *)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 = (char *)HSTRERROR( rc ); return rc; } #if defined( HAVE_GETHOSTBYADDR_R ) for(;buflen<BUFMAX;) { if (safe_realloc( &buf, buflen )==NULL) { *err = (char *)STRERROR( ENOMEM ); return ENOMEM; } #if (GETHOSTBYADDR_R_NARGS < 8) hp=gethostbyaddr_r( addr, alen, sa->sa_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 = (char *)HSTRERROR( 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 = (char *)HSTRERROR( 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 */ }
/* port = 0 indicates AF_LOCAL */ static int slap_get_listener_addresses( const char *host, unsigned short port, struct sockaddr ***sal) { struct sockaddr **sap; #ifdef LDAP_PF_LOCAL if ( port == 0 ) { *sal = ch_malloc(2 * sizeof(void *)); if (*sal == NULL) { return -1; } sap = *sal; *sap = ch_malloc(sizeof(struct sockaddr_un)); if (*sap == NULL) goto errexit; sap[1] = NULL; if ( strlen(host) > (sizeof(((struct sockaddr_un *)*sap)->sun_path) - 1) ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slap_get_listener_addresses: domain socket path (%s) " "too long in URL\n", host, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "daemon: domain socket path (%s) too long in URL", host, 0, 0); #endif goto errexit; } (void)memset( (void *)*sap, '\0', sizeof(struct sockaddr_un) ); (*sap)->sa_family = AF_LOCAL; strcpy( ((struct sockaddr_un *)*sap)->sun_path, host ); } else #endif { #ifdef HAVE_GETADDRINFO struct addrinfo hints, *res, *sai; int n, err; char serv[7]; memset( &hints, '\0', sizeof(hints) ); hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; hints.ai_family = slap_inet4or6; snprintf(serv, sizeof serv, "%d", port); if ( (err = getaddrinfo(host, serv, &hints, &res)) ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slap_get_listener_addresses: getaddrinfo failed: %s\n", AC_GAI_STRERROR(err), 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "daemon: getaddrinfo failed: %s\n", AC_GAI_STRERROR(err), 0, 0); #endif return -1; } sai = res; for (n=2; (sai = sai->ai_next) != NULL; n++) { /* EMPTY */ ; } *sal = ch_calloc(n, sizeof(void *)); if (*sal == NULL) { return -1; } sap = *sal; *sap = NULL; for ( sai=res; sai; sai=sai->ai_next ) { if( sai->ai_addr == NULL ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slap_get_listener_addresses: " "getaddrinfo ai_addr is NULL?\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "slap_get_listener_addresses: " "getaddrinfo ai_addr is NULL?\n", 0, 0, 0 ); #endif freeaddrinfo(res); goto errexit; } switch (sai->ai_family) { # ifdef LDAP_PF_INET6 case AF_INET6: *sap = ch_malloc(sizeof(struct sockaddr_in6)); if (*sap == NULL) { freeaddrinfo(res); goto errexit; } *(struct sockaddr_in6 *)*sap = *((struct sockaddr_in6 *)sai->ai_addr); break; # endif case AF_INET: *sap = ch_malloc(sizeof(struct sockaddr_in)); if (*sap == NULL) { freeaddrinfo(res); goto errexit; } *(struct sockaddr_in *)*sap = *((struct sockaddr_in *)sai->ai_addr); break; default: *sap = NULL; break; } if (*sap != NULL) { (*sap)->sa_family = sai->ai_family; sap++; *sap = NULL; } } freeaddrinfo(res); #else int i, n = 1; struct in_addr in; struct hostent *he = NULL; if ( host == NULL ) { in.s_addr = htonl(INADDR_ANY); } else if ( !inet_aton( host, &in ) ) { he = gethostbyname( host ); if( he == NULL ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slap_get_listener_addresses: invalid host %s\n", host, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "daemon: invalid host %s", host, 0, 0); #endif return -1; } for (n = 0; he->h_addr_list[n]; n++) ; } *sal = ch_malloc((n+1) * sizeof(void *)); if (*sal == NULL) { return -1; } sap = *sal; for ( i = 0; i<n; i++ ) { sap[i] = ch_malloc(sizeof(struct sockaddr_in)); if (*sap == NULL) { goto errexit; } (void)memset( (void *)sap[i], '\0', sizeof(struct sockaddr_in) ); sap[i]->sa_family = AF_INET; ((struct sockaddr_in *)sap[i])->sin_port = htons(port); if (he) { AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr, he->h_addr_list[i], sizeof(struct in_addr) ); } else { AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr, &in, sizeof(struct in_addr) ); } } sap[i] = NULL; #endif } return 0; errexit: slap_free_listener_addresses(*sal); return -1; }