~ubuntu-branches/ubuntu/hardy/exim4/hardy-proposed

« back to all changes in this revision

Viewing changes to src/host.c

  • Committer: Bazaar Package Importer
  • Author(s): Marc Haber
  • Date: 2005-07-02 06:08:34 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050702060834-qk17pd52kb9nt3bj
Tags: 4.52-1
* new upstream version 4.51. (mh)
  * adapt 70_remove_exim-users_references
  * remove 37_gnutlsparams
  * adapt 36_pcre
  * adapt 31_eximmanpage
* fix package priorities to have them in sync with override again. (mh)
* Fix error in nb (Norwegian) translation.
  Thanks to Helge Hafting. (mh). Closes: #315775
* Standards-Version: 3.6.2, no changes needed. (mh)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Cambridge: exim/exim-src/src/host.c,v 1.10 2005/06/22 15:44:38 ph10 Exp $ */
 
2
 
1
3
/*************************************************
2
4
*     Exim - an Internet mail transport agent    *
3
5
*************************************************/
4
6
 
5
 
/* Copyright (c) University of Cambridge 1995 - 2004 */
 
7
/* Copyright (c) University of Cambridge 1995 - 2005 */
6
8
/* See the file NOTICE for conditions of use and distribution. */
7
9
 
8
10
/* Functions for finding hosts, either by gethostbyname(), gethostbyaddr(), or
89
91
 
90
92
 
91
93
/*************************************************
 
94
*         Sort addresses when testing            *
 
95
*************************************************/
 
96
 
 
97
/* This function is called only when running in the test harness. It sorts a
 
98
number of multihomed host IP addresses into the order, so as to get
 
99
repeatability. This doesn't have to be efficient. But don't interchange IPv4
 
100
and IPv6 addresses!
 
101
 
 
102
Arguments:
 
103
  host        -> the first host item
 
104
  last        -> the last host item
 
105
 
 
106
Returns:      nothing
 
107
*/
 
108
 
 
109
static void
 
110
sort_addresses(host_item *host, host_item *last)
 
111
{
 
112
BOOL done = FALSE;
 
113
while (!done)
 
114
  {
 
115
  host_item *h;
 
116
  done = TRUE;
 
117
  for (h = host; h != last; h = h->next)
 
118
    {
 
119
    if ((Ustrchr(h->address, ':') == NULL) !=
 
120
        (Ustrchr(h->next->address, ':') == NULL))
 
121
      continue;
 
122
    if (Ustrcmp(h->address, h->next->address) > 0)
 
123
      {
 
124
      uschar *temp = h->address;
 
125
      h->address = h->next->address;
 
126
      h->next->address = temp;
 
127
      done = FALSE;
 
128
      }
 
129
    }
 
130
  }
 
131
}
 
132
 
 
133
 
 
134
 
 
135
/*************************************************
92
136
*       Build chain of host items from list      *
93
137
*************************************************/
94
138
 
323
367
    }
324
368
 
325
369
  sender_rcvhost[ptr] = 0;   /* string_cat() always leaves room */
 
370
 
 
371
  /* Release store, because string_cat allocated a minimum of 100 bytes that
 
372
  are rarely completely used. */
 
373
 
 
374
  store_reset(sender_rcvhost + ptr + 1);
326
375
  }
327
376
 
328
377
/* Host name is known and verified. */
392
441
else
393
442
  {
394
443
  uschar *flag = useflag? US"H=" : US"";
 
444
  uschar *iface = US"";
 
445
  if ((log_extra_selector & LX_incoming_interface) != 0 &&
 
446
       interface_address != NULL)
 
447
    iface = string_sprintf(" I=[%s]:%d", interface_address, interface_port);
395
448
  if (sender_ident == NULL)
396
 
    (void)string_format(big_buffer, big_buffer_size, "%s%s",
397
 
      flag, sender_fullhost);
 
449
    (void)string_format(big_buffer, big_buffer_size, "%s%s%s",
 
450
      flag, sender_fullhost, iface);
398
451
  else
399
 
    (void)string_format(big_buffer, big_buffer_size, "%s%s U=%s",
400
 
      flag, sender_fullhost, sender_ident);
 
452
    (void)string_format(big_buffer, big_buffer_size, "%s%s%s U=%s",
 
453
      flag, sender_fullhost, iface, sender_ident);
401
454
  }
402
455
return big_buffer;
403
456
}
440
493
while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
441
494
  {
442
495
  int port = host_extract_port(s);            /* Leaves just the IP address */
443
 
  if (!string_is_ip_address(s, NULL))
 
496
  if (string_is_ip_address(s, NULL) == 0)
444
497
    log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Malformed IP address \"%s\" in %s",
445
498
      s, name);
446
499
 
682
735
int x[4];
683
736
int v4offset = 0;
684
737
 
685
 
/* Handle IPv6 address, which may end with an IPv4 address */
 
738
/* Handle IPv6 address, which may end with an IPv4 address. It may also end
 
739
with a "scope", introduced by a percent sign. This code is NOT enclosed in #if
 
740
HAVE_IPV6 in order that IPv6 addresses are recognized even if IPv6 is not
 
741
supported. */
686
742
 
687
 
#if HAVE_IPV6
688
743
if (Ustrchr(address, ':') != NULL)
689
744
  {
690
745
  uschar *p = address;
700
755
 
701
756
  if (*p == ':') p++;
702
757
 
703
 
  /* Split the address into components separated by colons. */
 
758
  /* Split the address into components separated by colons. The input address
 
759
  is supposed to be checked for syntax. There was a case where this was
 
760
  overlooked; to guard against that happening again, check here and crash if
 
761
  there are too many components. */
704
762
 
705
 
  while (*p != 0)
 
763
  while (*p != 0 && *p != '%')
706
764
    {
707
 
    int len = Ustrcspn(p, ":");
 
765
    int len = Ustrcspn(p, ":%");
708
766
    if (len == 0) nulloffset = ci;
 
767
    if (ci > 7) log_write(0, LOG_MAIN|LOG_PANIC_DIE,
 
768
      "Internal error: invalid IPv6 address \"%s\" passed to host_aton()",
 
769
      address);
709
770
    component[ci++] = p;
710
771
    p += len;
711
772
    if (*p == ':') p++;
745
806
 
746
807
  if (!ipv4_ends) return 4;
747
808
  }
748
 
#endif
749
809
 
750
810
/* Handle IPv4 address */
751
811
 
752
 
sscanf(CS address, "%d.%d.%d.%d", x, x+1, x+2, x+3);
 
812
(void)sscanf(CS address, "%d.%d.%d.%d", x, x+1, x+2, x+3);
753
813
bin[v4offset] = (x[0] << 24) + (x[1] << 16) + (x[2] << 8) + x[3];
754
814
return v4offset+1;
755
815
}
803
863
/* We can't use host_ntoa() because it assumes the binary values are in network
804
864
byte order, and these are the result of host_aton(), which puts them in ints in
805
865
host byte order. Also, we really want IPv6 addresses to be in a canonical
806
 
format, so we output them with no abbreviation. However, we can't use the
807
 
normal colon separator in them because it terminates keys in lsearch files, so
808
 
use dot instead.
 
866
format, so we output them with no abbreviation. In a number of cases we can't
 
867
use the normal colon separator in them because it terminates keys in lsearch
 
868
files, so we want to use dot instead. There's an argument that specifies what
 
869
to use for IPv6 addresses.
809
870
 
810
871
Arguments:
811
872
  count       1 or 4 (number of ints)
812
873
  binary      points to the ints
813
874
  mask        mask value; if < 0 don't add to result
814
875
  buffer      big enough to hold the result
 
876
  sep         component separator character for IPv6 addresses
815
877
 
816
878
Returns:      the number of characters placed in buffer, not counting
817
879
              the final nul.
818
880
*/
819
881
 
820
882
int
821
 
host_nmtoa(int count, int *binary, int mask, uschar *buffer)
 
883
host_nmtoa(int count, int *binary, int mask, uschar *buffer, int sep)
822
884
{
823
885
int i, j;
824
886
uschar *tt = buffer;
837
899
  for (i = 0; i < 4; i++)
838
900
    {
839
901
    j = binary[i];
840
 
    sprintf(CS tt, "%04x.%04x.", (j >> 16) & 0xffff, j & 0xffff);
 
902
    sprintf(CS tt, "%04x%c%04x%c", (j >> 16) & 0xffff, sep, j & 0xffff, sep);
841
903
    while (*tt) tt++;
842
904
    }
843
905
  }
844
906
 
845
 
tt--;   /* lose final . */
 
907
tt--;   /* lose final separator */
846
908
 
847
909
if (mask < 0)
848
910
  *tt = 0;
858
920
 
859
921
 
860
922
/*************************************************
 
923
*        Check port for tls_on_connect           *
 
924
*************************************************/
 
925
 
 
926
/* This function checks whether a given incoming port is configured for tls-
 
927
on-connect. It is called from the daemon and from inetd handling. If the global
 
928
option tls_on_connect is already set, all ports operate this way. Otherwise, we
 
929
check the tls_on_connect_ports option for a list of ports.
 
930
 
 
931
Argument:  a port number
 
932
Returns:   TRUE or FALSE
 
933
*/
 
934
 
 
935
BOOL
 
936
host_is_tls_on_connect_port(int port)
 
937
{
 
938
int sep = 0;
 
939
uschar buffer[32];
 
940
uschar *list = tls_on_connect_ports;
 
941
uschar *s;
 
942
 
 
943
if (tls_on_connect) return TRUE;
 
944
 
 
945
while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
 
946
  {
 
947
  uschar *end;
 
948
  int lport = Ustrtol(s, &end, 10);
 
949
  if (*end != 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "tls_on_connect_ports "
 
950
    "contains \"%s\", which is not a port number: exim abandoned", s);
 
951
  if (lport == port) return TRUE;
 
952
  }
 
953
 
 
954
return FALSE;
 
955
}
 
956
 
 
957
 
 
958
 
 
959
/*************************************************
861
960
*        Check whether host is in a network      *
862
961
*************************************************/
863
962
 
1237
1336
 
1238
1337
The variable host_lookup_msg is set to an empty string on sucess, or to a
1239
1338
reason for the failure otherwise, in a form suitable for tagging onto an error
1240
 
message, and also host_lookup_failed is set TRUE if the lookup failed. Any
1241
 
dynamically constructed string for host_lookup_msg must be in permanent store,
1242
 
because it might be used for several incoming messages on the same SMTP
 
1339
message, and also host_lookup_failed is set TRUE if the lookup failed. If there
 
1340
was a defer, host_lookup_deferred is set TRUE.
 
1341
 
 
1342
Any dynamically constructed string for host_lookup_msg must be in permanent
 
1343
store, because it might be used for several incoming messages on the same SMTP
1243
1344
connection. */
1244
1345
 
1245
1346
int
1256
1357
dns_answer dnsa;
1257
1358
dns_scan dnss;
1258
1359
 
 
1360
host_lookup_deferred = host_lookup_failed = FALSE;
 
1361
 
1259
1362
HDEBUG(D_host_lookup)
1260
1363
  debug_printf("looking up host name for %s\n", sender_host_address);
1261
1364
 
1267
1370
  {
1268
1371
  HDEBUG(D_host_lookup)
1269
1372
    debug_printf("Test harness: host name lookup returns DEFER\n");
 
1373
  host_lookup_deferred = TRUE;
1270
1374
  return DEFER;
1271
1375
  }
1272
1376
 
1356
1460
      {
1357
1461
      HDEBUG(D_host_lookup)
1358
1462
        debug_printf("IP address PTR lookup gave temporary error\n");
 
1463
      host_lookup_deferred = TRUE;
1359
1464
      return DEFER;
1360
1465
      }
1361
1466
    }
1366
1471
    {
1367
1472
    HDEBUG(D_host_lookup)
1368
1473
      debug_printf("IP address lookup using gethostbyaddr()\n");
1369
 
 
1370
1474
    rc = host_name_lookup_byaddr();
1371
 
    if (rc == DEFER) return rc;        /* Can't carry on */
 
1475
    if (rc == DEFER)
 
1476
      {
 
1477
      host_lookup_deferred = TRUE;
 
1478
      return rc;                       /* Can't carry on */
 
1479
      }
1372
1480
    if (rc == OK) break;               /* Found a name */
1373
1481
    }
1374
1482
  }      /* Loop for bydns/byaddr scanning */
1382
1490
    log_write(L_host_lookup_failed, LOG_MAIN, "no host name found for IP "
1383
1491
      "address %s", sender_host_address);
1384
1492
  host_lookup_msg = US" (failed to find host name from IP address)";
1385
 
 
1386
 
host_lookup_failed = TRUE;
 
1493
  host_lookup_failed = TRUE;
1387
1494
  return FAIL;
1388
1495
  }
1389
1496
 
1471
1578
  else if (rc == HOST_FIND_AGAIN)
1472
1579
    {
1473
1580
    HDEBUG(D_host_lookup) debug_printf("temporary error for host name lookup\n");
 
1581
    host_lookup_deferred = TRUE;
1474
1582
    return DEFER;
1475
1583
    }
1476
1584
  else
1515
1623
host_lookup_msg = string_sprintf(" (%s does not match any IP address for %s)",
1516
1624
  sender_host_address, save_hostname);
1517
1625
store_pool = old_pool;
1518
 
 
1519
1626
host_lookup_failed = TRUE;
1520
1627
return FAIL;
1521
1628
}
1565
1672
uschar **addrlist;
1566
1673
host_item *last = NULL;
1567
1674
BOOL temp_error = FALSE;
 
1675
#if HAVE_IPV6
 
1676
int af;
 
1677
#endif
 
1678
 
 
1679
/* If we are in the test harness, a name ending in .test.again.dns always
 
1680
forces a temporary error response. */
 
1681
 
 
1682
if (running_in_test_harness)
 
1683
  {
 
1684
  uschar *endname = host->name + Ustrlen(host->name);
 
1685
  if (Ustrcmp(endname - 14, "test.again.dns") == 0)
 
1686
    return HOST_FIND_AGAIN;
 
1687
  }
1568
1688
 
1569
1689
/* In an IPv6 world, we need to scan for both kinds of address, so go round the
1570
1690
loop twice. Note that we have ensured that AF_INET6 is defined even in an IPv4
1573
1693
standalone). */
1574
1694
 
1575
1695
#if HAVE_IPV6
1576
 
  int af;
1577
 
 
1578
1696
  #ifndef STAND_ALONE
1579
1697
  if (dns_ipv4_lookup != NULL &&
1580
1698
        match_isinlist(host->name, &dns_ipv4_lookup, 0, NULL, NULL, MCL_DOMAIN,
1743
1861
  host_scan_for_local_hosts(host, &last, NULL) : HOST_FOUND;
1744
1862
 
1745
1863
/* When running in the test harness, sort into the order of addresses so as to
1746
 
get repeatability. This doesn't have to be efficient. But don't interchange
1747
 
IPv4 and IPv6 addresses! */
 
1864
get repeatability. */
1748
1865
 
1749
 
if (running_in_test_harness)
1750
 
  {
1751
 
  BOOL done = FALSE;
1752
 
  while (!done)
1753
 
    {
1754
 
    host_item *h;
1755
 
    done = TRUE;
1756
 
    for (h = host; h != last; h = h->next)
1757
 
      {
1758
 
      if ((Ustrchr(h->address, ':') == NULL) !=
1759
 
          (Ustrchr(h->next->address, ':') == NULL))
1760
 
        continue;
1761
 
      if (Ustrcmp(h->address, h->next->address) > 0)
1762
 
        {
1763
 
        uschar *temp = h->address;
1764
 
        h->address = h->next->address;
1765
 
        h->next->address = temp;
1766
 
        done = FALSE;
1767
 
        }
1768
 
      }
1769
 
    }
1770
 
  }
 
1866
if (running_in_test_harness) sort_addresses(host, last);
1771
1867
 
1772
1868
HDEBUG(D_host_lookup)
1773
1869
  {
2066
2162
                          HOST_FIND_BY_SRV  => look for SRV
2067
2163
                          HOST_FIND_BY_MX   => look for MX
2068
2164
                          HOST_FIND_BY_A    => look for A or AAAA
 
2165
                        also flags indicating how the lookup is done
 
2166
                          HOST_FIND_QUALIFY_SINGLE   ) passed to the
 
2167
                          HOST_FIND_SEARCH_PARENTS   )   resolver
2069
2168
  srv_service           when SRV used, the service name
2070
 
  qualify_single        if TRUE, ask DNS to qualify single-component names
2071
 
  search_parents        if TRUE, asd DNS to search parent domains
 
2169
  srv_fail_domains      DNS errors for these domains => assume nonexist
 
2170
  mx_fail_domains       DNS errors for these domains => assume nonexist
2072
2171
  fully_qualified_name  if not NULL, return fully-qualified name
2073
2172
  removed               set TRUE if local host was removed from the list
2074
2173
 
2085
2184
 
2086
2185
int
2087
2186
host_find_bydns(host_item *host, uschar *ignore_target_hosts, int whichrrs,
2088
 
  uschar *srv_service, BOOL qualify_single, BOOL search_parents,
 
2187
  uschar *srv_service, uschar *srv_fail_domains, uschar *mx_fail_domains,
2089
2188
  uschar **fully_qualified_name, BOOL *removed)
2090
2189
{
2091
2190
host_item *h, *last;
2101
2200
that gets set for DNS syntax check errors. */
2102
2201
 
2103
2202
if (fully_qualified_name != NULL) *fully_qualified_name = host->name;
2104
 
dns_init(qualify_single, search_parents);
 
2203
dns_init((whichrrs & HOST_FIND_QUALIFY_SINGLE) != 0,
 
2204
         (whichrrs & HOST_FIND_SEARCH_PARENTS) != 0);
2105
2205
host_find_failed_syntax = FALSE;
2106
2206
 
2107
2207
/* First, if requested, look for SRV records. The service name is given; we
2126
2226
  if (temp_fully_qualified_name != buffer && fully_qualified_name != NULL)
2127
2227
    *fully_qualified_name = temp_fully_qualified_name + prefix_length;
2128
2228
 
2129
 
  if (rc == DNS_FAIL || rc == DNS_AGAIN) return HOST_FIND_AGAIN;
 
2229
  /* On DNS failures, we give the "try again" error unless the domain is
 
2230
  listed as one for which we continue. */
 
2231
 
 
2232
  if (rc == DNS_FAIL || rc == DNS_AGAIN)
 
2233
    {
 
2234
    if (match_isinlist(host->name, &srv_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
 
2235
        TRUE, NULL) != OK)
 
2236
      return HOST_FIND_AGAIN;
 
2237
    DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
 
2238
      "(domain in srv_fail_domains)\n", (rc == DNS_FAIL)? "FAIL":"AGAIN");
 
2239
    }
2130
2240
  }
2131
2241
 
2132
2242
/* If we did not find any SRV records, search the DNS for MX records, if
2133
2243
requested to do so. If the result is DNS_NOMATCH, it means there is no such
2134
2244
domain, and there's no point in going on to look for address records with the
2135
2245
same domain. The result will be DNS_NODATA if the domain exists but has no MX
2136
 
records. */
 
2246
records. On DNS failures, we give the "try again" error unless the domain is
 
2247
listed as one for which we continue. */
2137
2248
 
2138
2249
if (rc != DNS_SUCCEED && (whichrrs & HOST_FIND_BY_MX) != 0)
2139
2250
  {
2140
2251
  ind_type = T_MX;
2141
2252
  rc = dns_lookup(&dnsa, host->name, ind_type, fully_qualified_name);
2142
 
  if (rc == DNS_FAIL || rc == DNS_AGAIN) return HOST_FIND_AGAIN;
2143
2253
  if (rc == DNS_NOMATCH) return HOST_FIND_FAILED;
 
2254
  if (rc == DNS_FAIL || rc == DNS_AGAIN)
 
2255
    {
 
2256
    if (match_isinlist(host->name, &mx_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
 
2257
        TRUE, NULL) != OK)
 
2258
      return HOST_FIND_AGAIN;
 
2259
    DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
 
2260
      "(domain in mx_fail_domains)\n", (rc == DNS_FAIL)? "FAIL":"AGAIN");
 
2261
    }
2144
2262
  }
2145
2263
 
2146
2264
/* If we haven't found anything yet, and we are requested to do so, try for an
2149
2267
 
2150
2268
if (rc != DNS_SUCCEED)
2151
2269
  {
2152
 
  if ((whichrrs &HOST_FIND_BY_A) == 0)
 
2270
  if ((whichrrs & HOST_FIND_BY_A) == 0)
2153
2271
    {
2154
2272
    DEBUG(D_host_lookup) debug_printf("Address records are not being sought\n");
2155
2273
    return HOST_FIND_FAILED;
2172
2290
  else
2173
2291
    if (rc == HOST_IGNORED) rc = HOST_FIND_FAILED;  /* No special action */
2174
2292
 
 
2293
  /* When running in the test harness, sort into the order of addresses so as
 
2294
  to get repeatability. */
 
2295
 
 
2296
  if (running_in_test_harness) sort_addresses(host, last);
 
2297
 
2175
2298
  DEBUG(D_host_lookup)
2176
2299
    {
2177
2300
    host_item *h;
2846
2969
  else if (Ustrcmp(buffer, "no_search_parents") == 0) search_parents = FALSE;
2847
2970
  else if (Ustrncmp(buffer, "retrans", 7) == 0)
2848
2971
    {
2849
 
    sscanf(CS(buffer+8), "%d", &dns_retrans);
 
2972
    (void)sscanf(CS(buffer+8), "%d", &dns_retrans);
2850
2973
    _res.retrans = dns_retrans;
2851
2974
    }
2852
2975
  else if (Ustrncmp(buffer, "retry", 5) == 0)
2853
2976
    {
2854
 
    sscanf(CS(buffer+6), "%d", &dns_retry);
 
2977
    (void)sscanf(CS(buffer+6), "%d", &dns_retry);
2855
2978
    _res.retry = dns_retry;
2856
2979
    }
2857
2980
  else if (alldigits(buffer))
2862
2985
    }
2863
2986
  else
2864
2987
    {
 
2988
    int flags = whichrrs;
 
2989
 
2865
2990
    h.name = buffer;
2866
2991
    h.next = NULL;
2867
2992
    h.mx = MX_NONE;
2870
2995
    h.why = hwhy_unknown;
2871
2996
    h.address = NULL;
2872
2997
 
 
2998
    if (qualify_single) flags |= HOST_FIND_QUALIFY_SINGLE;
 
2999
    if (search_parents) flags |= HOST_FIND_SEARCH_PARENTS;
 
3000
 
2873
3001
    rc = byname?
2874
3002
      host_find_byname(&h, NULL, &fully_qualified_name, TRUE)
2875
3003
      :
2876
 
      host_find_bydns(&h, NULL, whichrrs, US"smtp", qualify_single,
2877
 
        search_parents, &fully_qualified_name, NULL);
 
3004
      host_find_bydns(&h, NULL, flags, US"smtp", NULL, NULL,
 
3005
        &fully_qualified_name, NULL);
2878
3006
 
2879
3007
    if (rc == HOST_FIND_FAILED) printf("Failed\n");
2880
3008
      else if (rc == HOST_FIND_AGAIN) printf("Again\n");