#include <sys_defs.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <netdb.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
#include <msg.h>
#include <vstring.h>
#include <mymalloc.h>
#include <inet_addr_list.h>
#include <stringops.h>
#include <mail_params.h>
#include <own_inet_addr.h>
#include <dns.h>
#include "lmtp.h"
#include "lmtp_addr.h"
static void lmtp_print_addr(char *what, DNS_RR *addr_list)
{
DNS_RR *addr;
struct in_addr in_addr;
msg_info("begin %s address list", what);
for (addr = addr_list; addr; addr = addr->next) {
if (addr->data_len > sizeof(addr)) {
msg_warn("skipping address length %d", addr->data_len);
} else {
memcpy((char *) &in_addr, addr->data, sizeof(in_addr));
msg_info("pref %4d host %s/%s",
addr->pref, addr->name,
inet_ntoa(in_addr));
}
}
msg_info("end %s address list", what);
}
static DNS_RR *lmtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRING *why)
{
char *myname = "lmtp_addr_one";
struct in_addr inaddr;
DNS_FIXED fixed;
DNS_RR *addr = 0;
DNS_RR *rr;
struct hostent *hp;
if (msg_verbose)
msg_info("%s: host %s", myname, host);
if (ISDIGIT(host[0]) && (inaddr.s_addr = inet_addr(host)) != INADDR_NONE) {
memset((char *) &fixed, 0, sizeof(fixed));
return (dns_rr_append(addr_list,
dns_rr_create(host, &fixed, pref,
(char *) &inaddr, sizeof(inaddr))));
}
if (var_disable_dns) {
memset((char *) &fixed, 0, sizeof(fixed));
if ((hp = gethostbyname(host)) == 0) {
vstring_sprintf(why, "%s: host not found", host);
lmtp_errno = LMTP_FAIL;
} else if (hp->h_addrtype != AF_INET) {
vstring_sprintf(why, "%s: host not found", host);
msg_warn("%s: unknown address family %d for %s",
myname, hp->h_addrtype, host);
lmtp_errno = LMTP_FAIL;
} else {
while (hp->h_addr_list[0]) {
addr_list = dns_rr_append(addr_list,
dns_rr_create(host, &fixed, pref,
hp->h_addr_list[0],
sizeof(inaddr)));
hp->h_addr_list++;
}
}
return (addr_list);
}
switch (dns_lookup(host, T_A, RES_DEFNAMES, &addr, (VSTRING *) 0, why)) {
case DNS_OK:
for (rr = addr; rr; rr = rr->next)
rr->pref = pref;
addr_list = dns_rr_append(addr_list, addr);
break;
default:
lmtp_errno = LMTP_RETRY;
break;
case DNS_NOTFOUND:
case DNS_FAIL:
lmtp_errno = LMTP_FAIL;
break;
}
return (addr_list);
}
DNS_RR *lmtp_host_addr(char *host, VSTRING *why)
{
DNS_RR *addr_list;
#define PREF0 0
addr_list = lmtp_addr_one((DNS_RR *) 0, host, PREF0, why);
if (msg_verbose)
lmtp_print_addr(host, addr_list);
return (addr_list);
}