checkalias.c
上传用户:xxcykj
上传日期:2007-01-04
资源大小:727k
文件大小:6k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. /*
  2.  * checkalias.c -- check to see if two hostnames or IP addresses are equivalent
  3.  *
  4.  * Copyright 1997 by Eric S. Raymond
  5.  * For license terms, see the file COPYING in this directory.
  6.  */
  7. #include "config.h"
  8. #ifdef HAVE_GETHOSTBYNAME
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <sys/types.h>
  13. #include <sys/socket.h>
  14. #include <netinet/in.h>
  15. #include <arpa/inet.h>
  16. #include <netdb.h>
  17. #include "i18n.h"
  18. #include "mx.h"
  19. #include "fetchmail.h"
  20. #define MX_RETRIES 3
  21. static int is_ip_alias(const char *name1,const char *name2)
  22. /*
  23.  * Given two hostnames as arguments, returns TRUE if they
  24.  * have at least one IP address in common.
  25.  * No check is done on errors returned by gethostbyname,
  26.  * the calling function does them.
  27.  */
  28. {
  29.     typedef unsigned char address_t[sizeof (struct in_addr)]; 
  30.     typedef struct _address_e
  31.     {
  32. struct _address_e *next;
  33. address_t address;
  34.     } 
  35.     address_e;
  36.     address_e *host_a_addr=0, *host_b_addr=0; /* assignments pacify -Wall */
  37.     address_e *dummy_addr;
  38.     int i;
  39.     struct hostent *hp;
  40.     char **p;
  41.  
  42.     hp = gethostbyname(name1);
  43.  
  44.     dummy_addr = (address_e *)NULL;
  45.     for (i=0,p = hp->h_addr_list; *p != 0; i++,p++)
  46.     {
  47. struct in_addr in;
  48. (void) memcpy(&in.s_addr, *p, sizeof (in.s_addr));
  49. xalloca(host_a_addr, address_e *, sizeof (address_e));
  50. memset (host_a_addr,0, sizeof (address_e));
  51. host_a_addr->next = dummy_addr;
  52. (void) memcpy(&host_a_addr->address, *p, sizeof (in.s_addr));
  53. dummy_addr = host_a_addr;
  54.     }
  55.     hp = gethostbyname(name2);
  56.     dummy_addr = (address_e *)NULL;
  57.     for (i=0,p = hp->h_addr_list; *p != 0; i++,p++)
  58.     {
  59. struct in_addr in;
  60. (void) memcpy(&in.s_addr, *p, sizeof (in.s_addr));
  61. xalloca(host_b_addr, address_e *, sizeof (address_e));
  62. memset (host_b_addr,0, sizeof (address_e));
  63. host_b_addr->next = dummy_addr;
  64. (void) memcpy(&host_b_addr->address, *p, sizeof (in.s_addr));
  65. dummy_addr = host_b_addr;
  66.     }
  67.     while (host_a_addr)
  68.     {
  69. while (host_b_addr)
  70. {
  71.     if (!memcmp(host_b_addr->address,host_a_addr->address, sizeof (address_t)))
  72. return (TRUE);
  73.     host_b_addr = host_b_addr->next;
  74. }
  75. host_a_addr = host_a_addr->next;
  76.     }
  77.     return (FALSE);
  78. }
  79. int is_host_alias(const char *name, struct query *ctl)
  80. /* determine whether name is a DNS alias of the mailserver for this query */
  81. {
  82.     struct hostent *he,*he_st;
  83.     struct mxentry *mxp, *mxrecords;
  84.     struct hostdata *lead_server = 
  85. ctl->server.lead_server ? ctl->server.lead_server : &ctl->server;
  86.     /*
  87.      * The first two checks are optimizations that will catch a good
  88.      * many cases.
  89.      *
  90.      * (1) check against the `true name' deduced from the poll label
  91.      * and the via option (if present) at the beginning of the poll cycle.  
  92.      * Odds are good this will either be the mailserver's FQDN or a suffix of
  93.      * it with the mailserver's domain's default host name omitted.
  94.      *
  95.      * (2) Then check the rest of the `also known as'
  96.      * cache accumulated by previous DNS checks.  This cache is primed
  97.      * by the aka list option.
  98.      *
  99.      * Any of these on a mail address is definitive.  Only if the
  100.      * name doesn't match any is it time to call the bind library.
  101.      * If this happens odds are good we're looking at an MX name.
  102.      */
  103.     if (strcasecmp(lead_server->truename, name) == 0)
  104. return(TRUE);
  105.     else if (str_in_list(&lead_server->akalist, name, TRUE))
  106. return(TRUE);
  107.     else if (!ctl->server.dns)
  108. return(FALSE);
  109. #ifndef HAVE_RES_SEARCH
  110.     return(FALSE);
  111. #else
  112.     /*
  113.      * The only code that calls the BIND library is here and in the
  114.      * start-of-run probe with gethostbyname(3) under ETRN/Kerberos.
  115.      *
  116.      * We know DNS service was up at the beginning of the run.
  117.      * If it's down, our nameserver has crashed.  We don't want to try
  118.      * delivering the current message or anything else from the
  119.      * current server until it's back up.
  120.      */
  121.     else if ((he = gethostbyname(name)) != (struct hostent *)NULL)
  122.     {
  123. if (strcasecmp(ctl->server.truename, he->h_name) == 0)
  124.     goto match;
  125.         else if (((he_st = gethostbyname(ctl->server.truename)) != (struct hostent *)NULL) && ctl->server.checkalias)
  126. {
  127.     if (outlevel >= O_DEBUG)
  128. report(stdout, _("Checking if %s is really the same node as %sn"),ctl->server.truename,name);
  129.     if (is_ip_alias(ctl->server.truename,name) == TRUE)
  130.     {
  131. if (outlevel >= O_DEBUG)
  132.     report(stdout, _("Yes, their IP addresses matchn"));
  133. goto match;
  134.     }
  135.     if (outlevel >= O_DEBUG)
  136. report(stdout, _("No, their IP addresses don't matchn"));
  137. }
  138. else
  139.     return(FALSE);
  140.     }
  141.     else
  142. switch (h_errno)
  143. {
  144. case HOST_NOT_FOUND: /* specified host is unknown */
  145. case NO_ADDRESS: /* valid, but does not have an IP address */
  146.     break;
  147. case NO_RECOVERY: /* non-recoverable name server error */
  148. case TRY_AGAIN: /* temporary error on authoritative server */
  149. default:
  150.     if (outlevel != O_SILENT)
  151. report_complete(stdout, "n"); /* terminate the progress message */
  152.     report(stderr,
  153. _("nameserver failure while looking for `%s' during poll of %s.n"),
  154. name, ctl->server.pollname);
  155.     ctl->errcount++;
  156.     break;
  157. }
  158.     /*
  159.      * We're only here if DNS was OK but the gethostbyname() failed
  160.      * with a HOST_NOT_FOUND or NO_ADDRESS error.
  161.      * Search for a name match on MX records pointing to the server.
  162.      */
  163.     h_errno = 0;
  164.     if ((mxrecords = getmxrecords(name)) == (struct mxentry *)NULL)
  165.     {
  166. switch (h_errno)
  167. {
  168. case HOST_NOT_FOUND: /* specified host is unknown */
  169. case NO_ADDRESS: /* valid, but does not have an IP address */
  170.     return(FALSE);
  171.     break;
  172. case NO_RECOVERY: /* non-recoverable name server error */
  173. case TRY_AGAIN: /* temporary error on authoritative server */
  174. default:
  175.     report(stderr,
  176. _("nameserver failure while looking for `%s' during poll of %s.n"),
  177. name, ctl->server.pollname);
  178.     ctl->errcount++;
  179.     break;
  180. }
  181.     }
  182.     else
  183.     {
  184. for (mxp = mxrecords; mxp->name; mxp++)
  185.     if (strcasecmp(ctl->server.truename, mxp->name) == 0)
  186. goto match;
  187. return(FALSE);
  188.     match:;
  189.     }
  190.     /* add this name to relevant server's `also known as' list */
  191.     save_str(&lead_server->akalist, name, 0);
  192.     return(TRUE);
  193. #endif /* HAVE_RES_SEARCH */
  194. }
  195. #endif /* HAVE_GETHOSTBYNAME */
  196. /* checkalias.c ends here */