void smtpd_peer_init(SMTPD_STATE *state) { struct sockaddr_in sin; SOCKADDR_SIZE len = sizeof(sin); struct hostent *hp; int i; /* * Avoid suprious complaints from Purify on Solaris. */ memset((char *) &sin, 0, len); /* * Look up the peer address information. */ if (getpeername(vstream_fileno(state->client), (struct sockaddr *) & sin, &len) >= 0) { errno = 0; } /* * If peer went away, give up. */ if (errno == ECONNRESET || errno == ECONNABORTED) { state->name = mystrdup(CLIENT_NAME_UNKNOWN); state->addr = mystrdup(CLIENT_ADDR_UNKNOWN); state->peer_code = SMTPD_PEER_CODE_PERM; } /* * Look up and "verify" the client hostname. */ else if (errno == 0 && sin.sin_family == AF_INET) { state->addr = mystrdup(inet_ntoa(sin.sin_addr)); hp = gethostbyaddr((char *) &(sin.sin_addr), sizeof(sin.sin_addr), AF_INET); if (hp == 0) { state->name = mystrdup(CLIENT_NAME_UNKNOWN); state->peer_code = (h_errno == TRY_AGAIN ? SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM); } else if (valid_hostaddr(hp->h_name, DONT_GRIPE)) { msg_warn("numeric result %s in address->name lookup for %s", hp->h_name, state->addr); state->name = mystrdup(CLIENT_NAME_UNKNOWN); state->peer_code = SMTPD_PEER_CODE_PERM; } else if (!valid_hostname(hp->h_name, DONT_GRIPE)) { state->name = mystrdup(CLIENT_NAME_UNKNOWN); state->peer_code = SMTPD_PEER_CODE_PERM; } else { state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */ state->peer_code = SMTPD_PEER_CODE_OK; /* * Reject the hostname if it does not list the peer address. */ #define REJECT_PEER_NAME(state, code) { \ myfree(state->name); \ state->name = mystrdup(CLIENT_NAME_UNKNOWN); \ state->peer_code = code; \ } hp = gethostbyname(state->name); /* clobbers hp->name!! */ if (hp == 0) { msg_warn("%s: hostname %s verification failed: %s", state->addr, state->name, HSTRERROR(h_errno)); REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ? SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM)); } else if (hp->h_length != sizeof(sin.sin_addr)) { msg_warn("%s: hostname %s verification failed: bad address size %d", state->addr, state->name, hp->h_length); REJECT_PEER_NAME(state, SMTPD_PEER_CODE_PERM); } else { for (i = 0; /* void */ ; i++) { if (hp->h_addr_list[i] == 0) { msg_warn("%s: address not listed for hostname %s", state->addr, state->name); REJECT_PEER_NAME(state, SMTPD_PEER_CODE_PERM); break; } if (memcmp(hp->h_addr_list[i], (char *) &sin.sin_addr, sizeof(sin.sin_addr)) == 0) break; /* keep peer name */ } } } } /* * If it's not Internet, assume the client is local, and avoid using the * naming service because that can hang when the machine is disconnected. */ else { state->name = mystrdup("localhost"); state->addr = mystrdup("127.0.0.1"); /* XXX bogus. */ state->peer_code = SMTPD_PEER_CODE_OK; } /* * Do the name[addr] formatting for pretty reports. */ state->namaddr = concatenate(state->name, "[", state->addr, "]", (char *) 0); }
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 */ }