2 * checkalias.c -- check to see if two hostnames or IP addresses are equivalent
4 * Copyright 1997 by Eric S. Raymond
5 * For license terms, see the file COPYING in this directory.
7 * i18n by Arnaldo Carvalho de Melo <acme@conectiva.com.br> 7-Nov-1998
10 #ifdef HAVE_GETHOSTBYNAME
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
21 #include "fetchmail.h"
25 static int is_ip_alias(const char *name1,const char *name2)
27 * Given two hostnames as arguments, returns TRUE if they
28 * have at least one IP address in common.
29 * No check is done on errors returned by gethostbyname,
30 * the calling function does them.
33 typedef unsigned char address_t[sizeof (struct in_addr)];
34 typedef struct _address_e
36 struct _address_e *next;
40 address_e *host_a_addr=0, *host_b_addr=0; /* assignments pacify -Wall */
41 address_e *dummy_addr;
47 hp = gethostbyname(name1);
49 dummy_addr = (address_e *)NULL;
51 for (i=0,p = hp->h_addr_list; *p != 0; i++,p++)
54 (void) memcpy(&in.s_addr, *p, sizeof (in.s_addr));
55 xalloca(host_a_addr, address_e *, sizeof (address_e));
56 memset (host_a_addr,0, sizeof (address_e));
57 host_a_addr->next = dummy_addr;
58 (void) memcpy(&host_a_addr->address, *p, sizeof (in.s_addr));
59 dummy_addr = host_a_addr;
62 hp = gethostbyname(name2);
64 dummy_addr = (address_e *)NULL;
65 for (i=0,p = hp->h_addr_list; *p != 0; i++,p++)
68 (void) memcpy(&in.s_addr, *p, sizeof (in.s_addr));
69 xalloca(host_b_addr, address_e *, sizeof (address_e));
70 memset (host_b_addr,0, sizeof (address_e));
71 host_b_addr->next = dummy_addr;
72 (void) memcpy(&host_b_addr->address, *p, sizeof (in.s_addr));
73 dummy_addr = host_b_addr;
80 if (!memcmp(host_b_addr->address,host_a_addr->address, sizeof (address_t)))
83 host_b_addr = host_b_addr->next;
85 host_a_addr = host_a_addr->next;
90 int is_host_alias(const char *name, struct query *ctl)
91 /* determine whether name is a DNS alias of the mailserver for this query */
93 struct hostent *he,*he_st;
94 struct mxentry *mxp, *mxrecords;
96 struct hostdata *lead_server =
97 ctl->server.lead_server ? ctl->server.lead_server : &ctl->server;
100 * The first two checks are optimizations that will catch a good
103 * (1) check against the `true name' deduced from the poll label
104 * and the via option (if present) at the beginning of the poll cycle.
105 * Odds are good this will either be the mailserver's FQDN or a suffix of
106 * it with the mailserver's domain's default host name omitted.
108 * (2) Then check the rest of the `also known as'
109 * cache accumulated by previous DNS checks. This cache is primed
110 * by the aka list option.
112 * Any of these on a mail address is definitive. Only if the
113 * name doesn't match any is it time to call the bind library.
114 * If this happens odds are good we're looking at an MX name.
116 if (strcasecmp(lead_server->truename, name) == 0)
118 else if (str_in_list(&lead_server->akalist, name, TRUE))
120 else if (!ctl->server.dns)
123 #ifndef HAVE_RES_SEARCH
127 * The only code that calls the BIND library is here and in the
128 * start-of-run probe with gethostbyname(3) under ETRN/Kerberos.
130 * We know DNS service was up at the beginning of the run.
131 * If it's down, our nameserver has crashed. We don't want to try
132 * delivering the current message or anything else from the
133 * current server until it's back up.
135 else if ((he = gethostbyname(name)) != (struct hostent *)NULL)
137 if (strcasecmp(ctl->server.truename, he->h_name) == 0)
139 else if (((he_st = gethostbyname(ctl->server.truename)) != (struct hostent *)NULL) && ctl->server.checkalias)
141 if (outlevel >= O_DEBUG)
142 error(0, 0, _("Checking if %s is really the same node as %s"),ctl->server.truename,name);
143 if (is_ip_alias(ctl->server.truename,name) == TRUE)
145 if (outlevel >= O_DEBUG)
146 error(0, 0, _("Yes, their IP addresses match"));
149 if (outlevel >= O_DEBUG)
150 error(0, 0, _("No, their IP addresses don't match"));
158 case HOST_NOT_FOUND: /* specified host is unknown */
159 case NO_ADDRESS: /* valid, but does not have an IP address */
162 case NO_RECOVERY: /* non-recoverable name server error */
163 case TRY_AGAIN: /* temporary error on authoritative server */
165 if (outlevel != O_SILENT)
166 putchar('\n'); /* terminate the progress message */
168 _("nameserver failure while looking for `%s' during poll of %s."),
169 name, ctl->server.pollname);
175 * We're only here if DNS was OK but the gethostbyname() failed
176 * with a HOST_NOT_FOUND or NO_ADDRESS error.
177 * Search for a name match on MX records pointing to the server.
180 if ((mxrecords = getmxrecords(name)) == (struct mxentry *)NULL)
184 case HOST_NOT_FOUND: /* specified host is unknown */
185 case NO_ADDRESS: /* valid, but does not have an IP address */
189 case NO_RECOVERY: /* non-recoverable name server error */
190 case TRY_AGAIN: /* temporary error on authoritative server */
193 _("nameserver failure while looking for `%s' during poll of %s."),
194 name, ctl->server.pollname);
201 for (mxp = mxrecords; mxp->name; mxp++)
202 if (strcasecmp(ctl->server.truename, mxp->name) == 0)
208 /* add this name to relevant server's `also known as' list */
209 save_str(&lead_server->akalist, name, 0);
211 #endif /* HAVE_RES_SEARCH */
213 #endif /* HAVE_GETHOSTBYNAME */
215 /* checkalias.c ends here */