Add comment about libdomainkeys 0.67 to README.UPDATING for 4.53.
[exim.git] / src / src / host.c
CommitLineData
5dd9625b 1/* $Cambridge: exim/src/src/host.c,v 1.13 2005/08/22 15:28:20 ph10 Exp $ */
059ec3d9
PH
2
3/*************************************************
4* Exim - an Internet mail transport agent *
5*************************************************/
6
c988f1f4 7/* Copyright (c) University of Cambridge 1995 - 2005 */
059ec3d9
PH
8/* See the file NOTICE for conditions of use and distribution. */
9
10/* Functions for finding hosts, either by gethostbyname(), gethostbyaddr(), or
11directly via the DNS. When IPv6 is supported, getipnodebyname() and
12getipnodebyaddr() may be used instead of gethostbyname() and gethostbyaddr(),
13if the newer functions are available. This module also contains various other
14functions concerned with hosts and addresses, and a random number function,
15used for randomizing hosts with equal MXs but available for use in other parts
16of Exim. */
17
18
19#include "exim.h"
20
21
22/* Static variable for preserving the list of interface addresses in case it is
23used more than once. */
24
25static ip_address_item *local_interface_data = NULL;
26
27
28#ifdef USE_INET_NTOA_FIX
29/*************************************************
30* Replacement for broken inet_ntoa() *
31*************************************************/
32
33/* On IRIX systems, gcc uses a different structure passing convention to the
34native libraries. This causes inet_ntoa() to always yield 0.0.0.0 or
35255.255.255.255. To get round this, we provide a private version of the
36function here. It is used only if USE_INET_NTOA_FIX is set, which should happen
37only when gcc is in use on an IRIX system. Code send to me by J.T. Breitner,
38with these comments:
39
40 code by Stuart Levy
41 as seen in comp.sys.sgi.admin
42
2548ba04
PH
43August 2005: Apparently this is also needed for AIX systems; USE_INET_NTOA_FIX
44should now be set for them as well.
45
059ec3d9
PH
46Arguments: sa an in_addr structure
47Returns: pointer to static text string
48*/
49
50char *
51inet_ntoa(struct in_addr sa)
52{
53static uschar addr[20];
54sprintf(addr, "%d.%d.%d.%d",
55 (US &sa.s_addr)[0],
56 (US &sa.s_addr)[1],
57 (US &sa.s_addr)[2],
58 (US &sa.s_addr)[3]);
59 return addr;
60}
61#endif
62
63
64
65/*************************************************
66* Random number generator *
67*************************************************/
68
69/* This is a simple pseudo-random number generator. It does not have to be
70very good for the uses to which it is put. When running the regression tests,
71start with a fixed seed.
72
73Arguments:
74 limit: one more than the largest number required
75
76Returns: a pseudo-random number in the range 0 to limit-1
77*/
78
79int
80random_number(int limit)
81{
82if (random_seed == 0)
83 {
84 if (running_in_test_harness) random_seed = 42; else
85 {
86 int p = (int)getpid();
87 random_seed = (int)time(NULL) ^ ((p << 16) | p);
88 }
89 }
90random_seed = 1103515245 * random_seed + 12345;
91return (unsigned int)(random_seed >> 16) % limit;
92}
93
94
95
d8ef3577
PH
96/*************************************************
97* Sort addresses when testing *
98*************************************************/
99
100/* This function is called only when running in the test harness. It sorts a
101number of multihomed host IP addresses into the order, so as to get
102repeatability. This doesn't have to be efficient. But don't interchange IPv4
103and IPv6 addresses!
104
105Arguments:
106 host -> the first host item
107 last -> the last host item
8e669ac1 108
d8ef3577 109Returns: nothing
8e669ac1 110*/
d8ef3577
PH
111
112static void
113sort_addresses(host_item *host, host_item *last)
114{
115BOOL done = FALSE;
116while (!done)
117 {
118 host_item *h;
119 done = TRUE;
120 for (h = host; h != last; h = h->next)
121 {
122 if ((Ustrchr(h->address, ':') == NULL) !=
123 (Ustrchr(h->next->address, ':') == NULL))
124 continue;
125 if (Ustrcmp(h->address, h->next->address) > 0)
126 {
127 uschar *temp = h->address;
128 h->address = h->next->address;
129 h->next->address = temp;
130 done = FALSE;
131 }
132 }
133 }
134}
135
136
137
059ec3d9
PH
138/*************************************************
139* Build chain of host items from list *
140*************************************************/
141
142/* This function builds a chain of host items from a textual list of host
143names. It does not do any lookups. If randomize is true, the chain is build in
144a randomized order. There may be multiple groups of independently randomized
145hosts; they are delimited by a host name consisting of just "+".
146
147Arguments:
148 anchor anchor for the chain
149 list text list
150 randomize TRUE for randomizing
151
152Returns: nothing
153*/
154
155void
156host_build_hostlist(host_item **anchor, uschar *list, BOOL randomize)
157{
158int sep = 0;
159int fake_mx = MX_NONE; /* This value is actually -1 */
160uschar *name;
161uschar buffer[1024];
162
163if (list == NULL) return;
164if (randomize) fake_mx--; /* Start at -2 for randomizing */
165
166*anchor = NULL;
167
168while ((name = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
169 {
170 host_item *h;
171
172 if (name[0] == '+' && name[1] == 0) /* "+" delimits a randomized group */
173 { /* ignore if not randomizing */
174 if (randomize) fake_mx--;
175 continue;
176 }
177
178 h = store_get(sizeof(host_item));
179 h->name = string_copy(name);
180 h->address = NULL;
181 h->port = PORT_NONE;
182 h->mx = fake_mx;
183 h->sort_key = randomize? (-fake_mx)*1000 + random_number(1000) : 0;
184 h->status = hstatus_unknown;
185 h->why = hwhy_unknown;
186 h->last_try = 0;
187
188 if (*anchor == NULL)
189 {
190 h->next = NULL;
191 *anchor = h;
192 }
193 else
194 {
195 host_item *hh = *anchor;
196 if (h->sort_key < hh->sort_key)
197 {
198 h->next = hh;
199 *anchor = h;
200 }
201 else
202 {
203 while (hh->next != NULL && h->sort_key >= (hh->next)->sort_key)
204 hh = hh->next;
205 h->next = hh->next;
206 hh->next = h;
207 }
208 }
209 }
210}
211
212
213
214
215
216/*************************************************
217* Extract port from address string *
218*************************************************/
219
220/* In the spool file, and in the -oMa and -oMi options, a host plus port is
221given as an IP address followed by a dot and a port number. This function
222decodes this.
223
224An alternative format for the -oMa and -oMi options is [ip address]:port which
225is what Exim 4 uses for output, because it seems to becoming commonly used,
226whereas the dot form confuses some programs/people. So we recognize that form
227too.
228
229Argument:
230 address points to the string; if there is a port, the '.' in the string
231 is overwritten with zero to terminate the address; if the string
232 is in the [xxx]:ppp format, the address is shifted left and the
233 brackets are removed
234
235Returns: 0 if there is no port, else the port number. If there's a syntax
236 error, leave the incoming address alone, and return 0.
237*/
238
239int
7cd1141b 240host_address_extract_port(uschar *address)
059ec3d9
PH
241{
242int port = 0;
243uschar *endptr;
244
245/* Handle the "bracketed with colon on the end" format */
246
247if (*address == '[')
248 {
249 uschar *rb = address + 1;
250 while (*rb != 0 && *rb != ']') rb++;
251 if (*rb++ == 0) return 0; /* Missing ]; leave invalid address */
252 if (*rb == ':')
253 {
254 port = Ustrtol(rb + 1, &endptr, 10);
255 if (*endptr != 0) return 0; /* Invalid port; leave invalid address */
256 }
257 else if (*rb != 0) return 0; /* Bad syntax; leave invalid address */
258 memmove(address, address + 1, rb - address - 2);
259 rb[-2] = 0;
260 }
261
262/* Handle the "dot on the end" format */
263
264else
265 {
266 int skip = -3; /* Skip 3 dots in IPv4 addresses */
267 address--;
268 while (*(++address) != 0)
269 {
270 int ch = *address;
271 if (ch == ':') skip = 0; /* Skip 0 dots in IPv6 addresses */
272 else if (ch == '.' && skip++ >= 0) break;
273 }
274 if (*address == 0) return 0;
275 port = Ustrtol(address + 1, &endptr, 10);
276 if (*endptr != 0) return 0; /* Invalid port; leave invalid address */
277 *address = 0;
278 }
279
280return port;
281}
282
283
7cd1141b
PH
284/*************************************************
285* Get port from a host item's name *
286*************************************************/
287
288/* This function is called when finding the IP address for a host that is in a
289list of hosts explicitly configured, such as in the manualroute router, or in a
290fallback hosts list. We see if there is a port specification at the end of the
291host name, and if so, remove it. A minimum length of 3 is required for the
292original name; nothing shorter is recognized as having a port.
293
294We test for a name ending with a sequence of digits; if preceded by colon we
295have a port if the character before the colon is ] and the name starts with [
296or if there are no other colons in the name (i.e. it's not an IPv6 address).
297
298Arguments: pointer to the host item
299Returns: a port number or PORT_NONE
300*/
301
302int
303host_item_get_port(host_item *h)
304{
305uschar *p;
306int port, x;
307int len = Ustrlen(h->name);
308
309if (len < 3 || (p = h->name + len - 1, !isdigit(*p))) return PORT_NONE;
310
311/* Extract potential port number */
312
313port = *p-- - '0';
314x = 10;
315
316while (p > h->name + 1 && isdigit(*p))
317 {
318 port += (*p-- - '0') * x;
319 x *= 10;
320 }
321
322/* The smallest value of p at this point is h->name + 1. */
323
324if (*p != ':') return PORT_NONE;
325
326if (p[-1] == ']' && h->name[0] == '[')
327 h->name = string_copyn(h->name + 1, p - h->name - 2);
328else if (Ustrchr(h->name, ':') == p)
329 h->name = string_copyn(h->name, p - h->name);
330else return PORT_NONE;
331
332DEBUG(D_route|D_host_lookup) debug_printf("host=%s port=%d\n", h->name, port);
333return port;
334}
335
336
059ec3d9
PH
337
338#ifndef STAND_ALONE /* Omit when standalone testing */
339
340/*************************************************
341* Build sender_fullhost and sender_rcvhost *
342*************************************************/
343
344/* This function is called when sender_host_name and/or sender_helo_name
345have been set. Or might have been set - for a local message read off the spool
346they won't be. In that case, do nothing. Otherwise, set up the fullhost string
347as follows:
348
349(a) No sender_host_name or sender_helo_name: "[ip address]"
350(b) Just sender_host_name: "host_name [ip address]"
351(c) Just sender_helo_name: "(helo_name) [ip address]"
352(d) The two are identical: "host_name [ip address]"
353(e) The two are different: "host_name (helo_name) [ip address]"
354
355If log_incoming_port is set, the sending host's port number is added to the IP
356address.
357
358This function also builds sender_rcvhost for use in Received: lines, whose
359syntax is a bit different. This value also includes the RFC 1413 identity.
360There wouldn't be two different variables if I had got all this right in the
361first place.
362
363Because this data may survive over more than one incoming SMTP message, it has
364to be in permanent store.
365
366Arguments: none
367Returns: nothing
368*/
369
370void
371host_build_sender_fullhost(void)
372{
373uschar *address;
374int old_pool = store_pool;
375
376if (sender_host_address == NULL) return;
377
378store_pool = POOL_PERM;
379
380/* Set up address, with or without the port. After discussion, it seems that
381the only format that doesn't cause trouble is [aaaa]:pppp. However, we can't
382use this directly as the first item for Received: because it ain't an RFC 2822
383domain. Sigh. */
384
385address = string_sprintf("[%s]:%d", sender_host_address, sender_host_port);
386if ((log_extra_selector & LX_incoming_port) == 0 || sender_host_port <= 0)
387 *(Ustrrchr(address, ':')) = 0;
388
389/* Host name is not verified */
390
391if (sender_host_name == NULL)
392 {
393 uschar *portptr = Ustrstr(address, "]:");
394 int size = 0;
395 int ptr = 0;
396 int adlen; /* Sun compiler doesn't like ++ in initializers */
397
398 adlen = (portptr == NULL)? Ustrlen(address) : (++portptr - address);
399 sender_fullhost = (sender_helo_name == NULL)? address :
400 string_sprintf("(%s) %s", sender_helo_name, address);
401
402 sender_rcvhost = string_cat(NULL, &size, &ptr, address, adlen);
403
404 if (sender_ident != NULL || sender_helo_name != NULL || portptr != NULL)
405 {
406 int firstptr;
407 sender_rcvhost = string_cat(sender_rcvhost, &size, &ptr, US" (", 2);
408 firstptr = ptr;
409
410 if (portptr != NULL)
411 sender_rcvhost = string_append(sender_rcvhost, &size, &ptr, 2, US"port=",
412 portptr + 1);
413
414 if (sender_helo_name != NULL)
415 sender_rcvhost = string_append(sender_rcvhost, &size, &ptr, 2,
416 (firstptr == ptr)? US"helo=" : US" helo=", sender_helo_name);
417
418 if (sender_ident != NULL)
419 sender_rcvhost = string_append(sender_rcvhost, &size, &ptr, 2,
420 (firstptr == ptr)? US"ident=" : US" ident=", sender_ident);
421
422 sender_rcvhost = string_cat(sender_rcvhost, &size, &ptr, US")", 1);
423 }
424
425 sender_rcvhost[ptr] = 0; /* string_cat() always leaves room */
426
427 /* Release store, because string_cat allocated a minimum of 100 bytes that
428 are rarely completely used. */
429
430 store_reset(sender_rcvhost + ptr + 1);
431 }
432
433/* Host name is known and verified. */
434
435else
436 {
437 int len;
5dd9625b
PH
438 BOOL no_helo = FALSE;
439
440 /* Comparing a HELO name to a host name is easy */
441
059ec3d9 442 if (sender_helo_name == NULL ||
5dd9625b
PH
443 strcmpic(sender_host_name, sender_helo_name) == 0)
444 no_helo = TRUE;
445
446 /* If HELO/EHLO was followed by an IP literal, it's much more messy because
447 of two features of IPv6. Firstly, there's the "IPv6:" prefix (Exim is liberal
448 and doesn't require this, for historical reasons). Secondly, an IPv6 address
449 may not be given in canonical form, so we have to canonicize it before
450 comparing. As it happens, the code works for both IPv4 and IPv6. */
451
452 else if (sender_helo_name[0] == '[' &&
453 sender_helo_name[(len=Ustrlen(sender_helo_name))-1] == ']')
454 {
455 uschar *helo_ip;
456 int offset = 1;
457
458 if (strncmpic(sender_helo_name+1, US"IPv6:",5) == 0) offset += 5;
459 helo_ip = string_copyn(sender_helo_name + offset, len - offset - 1);
460
461 if (string_is_ip_address(helo_ip, NULL) != 0)
462 {
463 int x[4];
464 int size;
465 size = host_aton(helo_ip, x);
466 helo_ip = store_get(48); /* large enough for full IPv6 */
467 (void)host_nmtoa(size, x, -1, helo_ip, ':');
468 if (strcmpic(helo_ip, sender_host_address) == 0) no_helo = TRUE;
469 }
470 }
471
472 if (no_helo)
059ec3d9
PH
473 {
474 sender_fullhost = string_sprintf("%s %s", sender_host_name, address);
475 sender_rcvhost = (sender_ident == NULL)?
476 string_sprintf("%s (%s)", sender_host_name, address) :
477 string_sprintf("%s (%s ident=%s)", sender_host_name, address,
478 sender_ident);
479 }
480 else
481 {
482 sender_fullhost = string_sprintf("%s (%s) %s", sender_host_name,
483 sender_helo_name, address);
484 sender_rcvhost = (sender_ident == NULL)?
485 string_sprintf("%s (%s helo=%s)", sender_host_name,
486 address, sender_helo_name) :
487 string_sprintf("%s\n\t(%s helo=%s ident=%s)", sender_host_name,
488 address, sender_helo_name, sender_ident);
489 }
490 }
491
492store_pool = old_pool;
493
494DEBUG(D_host_lookup) debug_printf("sender_fullhost = %s\n", sender_fullhost);
495DEBUG(D_host_lookup) debug_printf("sender_rcvhost = %s\n", sender_rcvhost);
496}
497
498
499
500/*************************************************
501* Build host+ident message *
502*************************************************/
503
504/* Used when logging rejections and various ACL and SMTP incidents. The text
505return depends on whether sender_fullhost and sender_ident are set or not:
506
507 no ident, no host => U=unknown
508 no ident, host set => H=sender_fullhost
509 ident set, no host => U=ident
510 ident set, host set => H=sender_fullhost U=ident
511
512Arguments:
513 useflag TRUE if first item to be flagged (H= or U=); if there are two
514 items, the second is always flagged
515
516Returns: pointer to a string in big_buffer
517*/
518
519uschar *
520host_and_ident(BOOL useflag)
521{
522if (sender_fullhost == NULL)
523 {
524 (void)string_format(big_buffer, big_buffer_size, "%s%s", useflag? "U=" : "",
525 (sender_ident == NULL)? US"unknown" : sender_ident);
526 }
527else
528 {
529 uschar *flag = useflag? US"H=" : US"";
530 uschar *iface = US"";
531 if ((log_extra_selector & LX_incoming_interface) != 0 &&
532 interface_address != NULL)
533 iface = string_sprintf(" I=[%s]:%d", interface_address, interface_port);
534 if (sender_ident == NULL)
535 (void)string_format(big_buffer, big_buffer_size, "%s%s%s",
536 flag, sender_fullhost, iface);
537 else
538 (void)string_format(big_buffer, big_buffer_size, "%s%s%s U=%s",
539 flag, sender_fullhost, iface, sender_ident);
540 }
541return big_buffer;
542}
543
544#endif /* STAND_ALONE */
545
546
547
548
549/*************************************************
550* Build list of local interfaces *
551*************************************************/
552
553/* This function interprets the contents of the local_interfaces or
554extra_local_interfaces options, and creates an ip_address_item block for each
555item on the list. There is no special interpretation of any IP addresses; in
556particular, 0.0.0.0 and ::0 are returned without modification. If any address
557includes a port, it is set in the block. Otherwise the port value is set to
558zero.
559
560Arguments:
561 list the list
562 name the name of the option being expanded
563
564Returns: a chain of ip_address_items, each containing to a textual
565 version of an IP address, and a port number (host order) or
566 zero if no port was given with the address
567*/
568
569ip_address_item *
570host_build_ifacelist(uschar *list, uschar *name)
571{
572int sep = 0;
573uschar *s;
574uschar buffer[64];
575ip_address_item *yield = NULL;
576ip_address_item *last = NULL;
577ip_address_item *next;
578
579while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
580 {
7cd1141b 581 int port = host_address_extract_port(s); /* Leaves just the IP address */
a5a28604 582 if (string_is_ip_address(s, NULL) == 0)
059ec3d9
PH
583 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Malformed IP address \"%s\" in %s",
584 s, name);
585
586 /* This use of strcpy() is OK because we have checked that s is a valid IP
587 address above. The field in the ip_address_item is large enough to hold an
588 IPv6 address. */
589
590 next = store_get(sizeof(ip_address_item));
591 next->next = NULL;
592 Ustrcpy(next->address, s);
593 next->port = port;
594 next->v6_include_v4 = FALSE;
595
596 if (yield == NULL) yield = last = next; else
597 {
598 last->next = next;
599 last = next;
600 }
601 }
602
603return yield;
604}
605
606
607
608
609
610/*************************************************
611* Find addresses on local interfaces *
612*************************************************/
613
614/* This function finds the addresses of local IP interfaces. These are used
615when testing for routing to the local host. As the function may be called more
616than once, the list is preserved in permanent store, pointed to by a static
617variable, to save doing the work more than once per process.
618
619The generic list of interfaces is obtained by calling host_build_ifacelist()
620for local_interfaces and extra_local_interfaces. This list scanned to remove
621duplicates (which may exist with different ports - not relevant here). If
622either of the wildcard IP addresses (0.0.0.0 and ::0) are encountered, they are
623replaced by the appropriate (IPv4 or IPv6) list of actual local interfaces,
624obtained from os_find_running_interfaces().
625
626Arguments: none
627Returns: a chain of ip_address_items, each containing to a textual
628 version of an IP address; the port numbers are not relevant
629*/
630
631
632/* First, a local subfunction to add an interface to a list in permanent store,
633but only if there isn't a previous copy of that address on the list. */
634
635static ip_address_item *
636add_unique_interface(ip_address_item *list, ip_address_item *ipa)
637{
638ip_address_item *ipa2;
639for (ipa2 = list; ipa2 != NULL; ipa2 = ipa2->next)
640 if (Ustrcmp(ipa2->address, ipa->address) == 0) return list;
641ipa2 = store_get_perm(sizeof(ip_address_item));
642*ipa2 = *ipa;
643ipa2->next = list;
644return ipa2;
645}
646
647
648/* This is the globally visible function */
649
650ip_address_item *
651host_find_interfaces(void)
652{
653ip_address_item *running_interfaces = NULL;
654
655if (local_interface_data == NULL)
656 {
657 void *reset_item = store_get(0);
658 ip_address_item *dlist = host_build_ifacelist(local_interfaces,
659 US"local_interfaces");
660 ip_address_item *xlist = host_build_ifacelist(extra_local_interfaces,
661 US"extra_local_interfaces");
662 ip_address_item *ipa;
663
664 if (dlist == NULL) dlist = xlist; else
665 {
666 for (ipa = dlist; ipa->next != NULL; ipa = ipa->next);
667 ipa->next = xlist;
668 }
669
670 for (ipa = dlist; ipa != NULL; ipa = ipa->next)
671 {
672 if (Ustrcmp(ipa->address, "0.0.0.0") == 0 ||
673 Ustrcmp(ipa->address, "::0") == 0)
674 {
675 ip_address_item *ipa2;
676 BOOL ipv6 = ipa->address[0] == ':';
677 if (running_interfaces == NULL)
678 running_interfaces = os_find_running_interfaces();
679 for (ipa2 = running_interfaces; ipa2 != NULL; ipa2 = ipa2->next)
680 {
681 if ((Ustrchr(ipa2->address, ':') != NULL) == ipv6)
682 local_interface_data = add_unique_interface(local_interface_data,
683 ipa2);
684 }
685 }
686 else
687 {
688 local_interface_data = add_unique_interface(local_interface_data, ipa);
689 DEBUG(D_interface)
690 {
691 debug_printf("Configured local interface: address=%s", ipa->address);
692 if (ipa->port != 0) debug_printf(" port=%d", ipa->port);
693 debug_printf("\n");
694 }
695 }
696 }
697 store_reset(reset_item);
698 }
699
700return local_interface_data;
701}
702
703
704
705
706
707/*************************************************
708* Convert network IP address to text *
709*************************************************/
710
711/* Given an IPv4 or IPv6 address in binary, convert it to a text
712string and return the result in a piece of new store. The address can
713either be given directly, or passed over in a sockaddr structure. Note
714that this isn't the converse of host_aton() because of byte ordering
715differences. See host_nmtoa() below.
716
717Arguments:
718 type if < 0 then arg points to a sockaddr, else
719 either AF_INET or AF_INET6
720 arg points to a sockaddr if type is < 0, or
721 points to an IPv4 address (32 bits), or
722 points to an IPv6 address (128 bits),
723 in both cases, in network byte order
724 buffer if NULL, the result is returned in gotten store;
725 else points to a buffer to hold the answer
726 portptr points to where to put the port number, if non NULL; only
727 used when type < 0
728
729Returns: pointer to character string
730*/
731
732uschar *
733host_ntoa(int type, const void *arg, uschar *buffer, int *portptr)
734{
735uschar *yield;
736
737/* The new world. It is annoying that we have to fish out the address from
738different places in the block, depending on what kind of address it is. It
739is also a pain that inet_ntop() returns a const uschar *, whereas the IPv4
740function inet_ntoa() returns just uschar *, and some picky compilers insist
741on warning if one assigns a const uschar * to a uschar *. Hence the casts. */
742
743#if HAVE_IPV6
744uschar addr_buffer[46];
745if (type < 0)
746 {
747 int family = ((struct sockaddr *)arg)->sa_family;
748 if (family == AF_INET6)
749 {
750 struct sockaddr_in6 *sk = (struct sockaddr_in6 *)arg;
751 yield = (uschar *)inet_ntop(family, &(sk->sin6_addr), CS addr_buffer,
752 sizeof(addr_buffer));
753 if (portptr != NULL) *portptr = ntohs(sk->sin6_port);
754 }
755 else
756 {
757 struct sockaddr_in *sk = (struct sockaddr_in *)arg;
758 yield = (uschar *)inet_ntop(family, &(sk->sin_addr), CS addr_buffer,
759 sizeof(addr_buffer));
760 if (portptr != NULL) *portptr = ntohs(sk->sin_port);
761 }
762 }
763else
764 {
765 yield = (uschar *)inet_ntop(type, arg, CS addr_buffer, sizeof(addr_buffer));
766 }
767
768/* If the result is a mapped IPv4 address, show it in V4 format. */
769
770if (Ustrncmp(yield, "::ffff:", 7) == 0) yield += 7;
771
772#else /* HAVE_IPV6 */
773
774/* The old world */
775
776if (type < 0)
777 {
778 yield = US inet_ntoa(((struct sockaddr_in *)arg)->sin_addr);
779 if (portptr != NULL) *portptr = ntohs(((struct sockaddr_in *)arg)->sin_port);
780 }
781else
782 yield = US inet_ntoa(*((struct in_addr *)arg));
783#endif
784
785/* If there is no buffer, put the string into some new store. */
786
787if (buffer == NULL) return string_copy(yield);
788
789/* Callers of this function with a non-NULL buffer must ensure that it is
790large enough to hold an IPv6 address, namely, at least 46 bytes. That's what
791makes this use of strcpy() OK. */
792
793Ustrcpy(buffer, yield);
794return buffer;
795}
796
797
798
799
800/*************************************************
801* Convert address text to binary *
802*************************************************/
803
804/* Given the textual form of an IP address, convert it to binary in an
805array of ints. IPv4 addresses occupy one int; IPv6 addresses occupy 4 ints.
806The result has the first byte in the most significant byte of the first int. In
807other words, the result is not in network byte order, but in host byte order.
808As a result, this is not the converse of host_ntoa(), which expects network
809byte order. See host_nmtoa() below.
810
811Arguments:
812 address points to the textual address, checked for syntax
813 bin points to an array of 4 ints
814
815Returns: the number of ints used
816*/
817
818int
819host_aton(uschar *address, int *bin)
820{
821int x[4];
822int v4offset = 0;
823
8e669ac1 824/* Handle IPv6 address, which may end with an IPv4 address. It may also end
7e634d24
PH
825with a "scope", introduced by a percent sign. This code is NOT enclosed in #if
826HAVE_IPV6 in order that IPv6 addresses are recognized even if IPv6 is not
827supported. */
059ec3d9
PH
828
829if (Ustrchr(address, ':') != NULL)
830 {
831 uschar *p = address;
832 uschar *component[8];
833 BOOL ipv4_ends = FALSE;
834 int ci = 0;
835 int nulloffset = 0;
836 int v6count = 8;
837 int i;
838
839 /* If the address starts with a colon, it will start with two colons.
840 Just lose the first one, which will leave a null first component. */
8e669ac1 841
059ec3d9
PH
842 if (*p == ':') p++;
843
8e669ac1
PH
844 /* Split the address into components separated by colons. The input address
845 is supposed to be checked for syntax. There was a case where this was
846 overlooked; to guard against that happening again, check here and crash if
7e634d24 847 there are too many components. */
059ec3d9 848
7e634d24 849 while (*p != 0 && *p != '%')
059ec3d9 850 {
7e634d24 851 int len = Ustrcspn(p, ":%");
059ec3d9 852 if (len == 0) nulloffset = ci;
8e669ac1 853 if (ci > 7) log_write(0, LOG_MAIN|LOG_PANIC_DIE,
b975ba52 854 "Internal error: invalid IPv6 address \"%s\" passed to host_aton()",
8e669ac1 855 address);
059ec3d9
PH
856 component[ci++] = p;
857 p += len;
858 if (*p == ':') p++;
859 }
860
861 /* If the final component contains a dot, it is a trailing v4 address.
862 As the syntax is known to be checked, just set up for a trailing
863 v4 address and restrict the v6 part to 6 components. */
864
865 if (Ustrchr(component[ci-1], '.') != NULL)
866 {
867 address = component[--ci];
868 ipv4_ends = TRUE;
869 v4offset = 3;
870 v6count = 6;
871 }
872
873 /* If there are fewer than 6 or 8 components, we have to insert some
874 more empty ones in the middle. */
875
876 if (ci < v6count)
877 {
878 int insert_count = v6count - ci;
879 for (i = v6count-1; i > nulloffset + insert_count; i--)
880 component[i] = component[i - insert_count];
881 while (i > nulloffset) component[i--] = US"";
882 }
883
884 /* Now turn the components into binary in pairs and bung them
885 into the vector of ints. */
886
887 for (i = 0; i < v6count; i += 2)
888 bin[i/2] = (Ustrtol(component[i], NULL, 16) << 16) +
889 Ustrtol(component[i+1], NULL, 16);
890
891 /* If there was no terminating v4 component, we are done. */
892
893 if (!ipv4_ends) return 4;
894 }
895
896/* Handle IPv4 address */
897
ff790e47 898(void)sscanf(CS address, "%d.%d.%d.%d", x, x+1, x+2, x+3);
059ec3d9
PH
899bin[v4offset] = (x[0] << 24) + (x[1] << 16) + (x[2] << 8) + x[3];
900return v4offset+1;
901}
902
903
904/*************************************************
905* Apply mask to an IP address *
906*************************************************/
907
908/* Mask an address held in 1 or 4 ints, with the ms bit in the ms bit of the
909first int, etc.
910
911Arguments:
912 count the number of ints
913 binary points to the ints to be masked
914 mask the count of ms bits to leave, or -1 if no masking
915
916Returns: nothing
917*/
918
919void
920host_mask(int count, int *binary, int mask)
921{
922int i;
923if (mask < 0) mask = 99999;
924for (i = 0; i < count; i++)
925 {
926 int wordmask;
927 if (mask == 0) wordmask = 0;
928 else if (mask < 32)
929 {
930 wordmask = (-1) << (32 - mask);
931 mask = 0;
932 }
933 else
934 {
935 wordmask = -1;
936 mask -= 32;
937 }
938 binary[i] &= wordmask;
939 }
940}
941
942
943
944
945/*************************************************
946* Convert masked IP address in ints to text *
947*************************************************/
948
949/* We can't use host_ntoa() because it assumes the binary values are in network
950byte order, and these are the result of host_aton(), which puts them in ints in
951host byte order. Also, we really want IPv6 addresses to be in a canonical
6f0c9a4f
PH
952format, so we output them with no abbreviation. In a number of cases we can't
953use the normal colon separator in them because it terminates keys in lsearch
8e669ac1 954files, so we want to use dot instead. There's an argument that specifies what
6f0c9a4f 955to use for IPv6 addresses.
059ec3d9
PH
956
957Arguments:
958 count 1 or 4 (number of ints)
959 binary points to the ints
960 mask mask value; if < 0 don't add to result
961 buffer big enough to hold the result
8e669ac1 962 sep component separator character for IPv6 addresses
059ec3d9
PH
963
964Returns: the number of characters placed in buffer, not counting
965 the final nul.
966*/
967
968int
6f0c9a4f 969host_nmtoa(int count, int *binary, int mask, uschar *buffer, int sep)
059ec3d9
PH
970{
971int i, j;
972uschar *tt = buffer;
973
974if (count == 1)
975 {
976 j = binary[0];
977 for (i = 24; i >= 0; i -= 8)
978 {
979 sprintf(CS tt, "%d.", (j >> i) & 255);
980 while (*tt) tt++;
981 }
982 }
983else
984 {
985 for (i = 0; i < 4; i++)
986 {
987 j = binary[i];
6f0c9a4f 988 sprintf(CS tt, "%04x%c%04x%c", (j >> 16) & 0xffff, sep, j & 0xffff, sep);
059ec3d9
PH
989 while (*tt) tt++;
990 }
991 }
992
6f0c9a4f 993tt--; /* lose final separator */
059ec3d9
PH
994
995if (mask < 0)
996 *tt = 0;
997else
998 {
999 sprintf(CS tt, "/%d", mask);
1000 while (*tt) tt++;
1001 }
1002
1003return tt - buffer;
1004}
1005
1006
1007
1008/*************************************************
1009* Check port for tls_on_connect *
1010*************************************************/
1011
1012/* This function checks whether a given incoming port is configured for tls-
1013on-connect. It is called from the daemon and from inetd handling. If the global
1014option tls_on_connect is already set, all ports operate this way. Otherwise, we
1015check the tls_on_connect_ports option for a list of ports.
1016
1017Argument: a port number
1018Returns: TRUE or FALSE
1019*/
1020
1021BOOL
1022host_is_tls_on_connect_port(int port)
1023{
1024int sep = 0;
1025uschar buffer[32];
1026uschar *list = tls_on_connect_ports;
1027uschar *s;
1028
1029if (tls_on_connect) return TRUE;
1030
1031while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
1032 {
1033 uschar *end;
1034 int lport = Ustrtol(s, &end, 10);
1035 if (*end != 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "tls_on_connect_ports "
1036 "contains \"%s\", which is not a port number: exim abandoned", s);
1037 if (lport == port) return TRUE;
1038 }
1039
1040return FALSE;
1041}
1042
1043
1044
1045/*************************************************
1046* Check whether host is in a network *
1047*************************************************/
1048
1049/* This function checks whether a given IP address matches a pattern that
1050represents either a single host, or a network (using CIDR notation). The caller
1051of this function must check the syntax of the arguments before calling it.
1052
1053Arguments:
1054 host string representation of the ip-address to check
1055 net string representation of the network, with optional CIDR mask
1056 maskoffset offset to the / that introduces the mask in the key
1057 zero if there is no mask
1058
1059Returns:
1060 TRUE the host is inside the network
1061 FALSE the host is NOT inside the network
1062*/
1063
1064BOOL
1065host_is_in_net(uschar *host, uschar *net, int maskoffset)
1066{
1067int i;
1068int address[4];
1069int incoming[4];
1070int mlen;
1071int size = host_aton(net, address);
1072int insize;
1073
1074/* No mask => all bits to be checked */
1075
1076if (maskoffset == 0) mlen = 99999; /* Big number */
1077 else mlen = Uatoi(net + maskoffset + 1);
1078
1079/* Convert the incoming address to binary. */
1080
1081insize = host_aton(host, incoming);
1082
1083/* Convert IPv4 addresses given in IPv6 compatible mode, which represent
1084 connections from IPv4 hosts to IPv6 hosts, that is, addresses of the form
1085 ::ffff:<v4address>, to IPv4 format. */
1086
1087if (insize == 4 && incoming[0] == 0 && incoming[1] == 0 &&
1088 incoming[2] == 0xffff)
1089 {
1090 insize = 1;
1091 incoming[0] = incoming[3];
1092 }
1093
1094/* No match if the sizes don't agree. */
1095
1096if (insize != size) return FALSE;
1097
1098/* Else do the masked comparison. */
1099
1100for (i = 0; i < size; i++)
1101 {
1102 int mask;
1103 if (mlen == 0) mask = 0;
1104 else if (mlen < 32)
1105 {
1106 mask = (-1) << (32 - mlen);
1107 mlen = 0;
1108 }
1109 else
1110 {
1111 mask = -1;
1112 mlen -= 32;
1113 }
1114 if ((incoming[i] & mask) != (address[i] & mask)) return FALSE;
1115 }
1116
1117return TRUE;
1118}
1119
1120
1121
1122/*************************************************
1123* Scan host list for local hosts *
1124*************************************************/
1125
1126/* Scan through a chain of addresses and check whether any of them is the
1127address of an interface on the local machine. If so, remove that address and
1128any previous ones with the same MX value, and all subsequent ones (which will
1129have greater or equal MX values) from the chain. Note: marking them as unusable
1130is NOT the right thing to do because it causes the hosts not to be used for
1131other domains, for which they may well be correct.
1132
1133The hosts may be part of a longer chain; we only process those between the
1134initial pointer and the "last" pointer.
1135
1136There is also a list of "pseudo-local" host names which are checked against the
1137host names. Any match causes that host item to be treated the same as one which
1138matches a local IP address.
1139
1140If the very first host is a local host, then all MX records had a precedence
1141greater than or equal to that of the local host. Either there's a problem in
1142the DNS, or an apparently remote name turned out to be an abbreviation for the
1143local host. Give a specific return code, and let the caller decide what to do.
1144Otherwise, give a success code if at least one host address has been found.
1145
1146Arguments:
1147 host pointer to the first host in the chain
1148 lastptr pointer to pointer to the last host in the chain (may be updated)
1149 removed if not NULL, set TRUE if some local addresses were removed
1150 from the list
1151
1152Returns:
1153 HOST_FOUND if there is at least one host with an IP address on the chain
1154 and an MX value less than any MX value associated with the
1155 local host
1156 HOST_FOUND_LOCAL if a local host is among the lowest-numbered MX hosts; when
1157 the host addresses were obtained from A records or
1158 gethostbyname(), the MX values are set to -1.
1159 HOST_FIND_FAILED if no valid hosts with set IP addresses were found
1160*/
1161
1162int
1163host_scan_for_local_hosts(host_item *host, host_item **lastptr, BOOL *removed)
1164{
1165int yield = HOST_FIND_FAILED;
1166host_item *last = *lastptr;
1167host_item *prev = NULL;
1168host_item *h;
1169
1170if (removed != NULL) *removed = FALSE;
1171
1172if (local_interface_data == NULL) local_interface_data = host_find_interfaces();
1173
1174for (h = host; h != last->next; h = h->next)
1175 {
1176 #ifndef STAND_ALONE
1177 if (hosts_treat_as_local != NULL)
1178 {
1179 int rc;
1180 uschar *save = deliver_domain;
1181 deliver_domain = h->name; /* set $domain */
1182 rc = match_isinlist(string_copylc(h->name), &hosts_treat_as_local, 0,
1183 &domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL);
1184 deliver_domain = save;
1185 if (rc == OK) goto FOUND_LOCAL;
1186 }
1187 #endif
1188
1189 /* It seems that on many operating systems, 0.0.0.0 is treated as a synonym
1190 for 127.0.0.1 and refers to the local host. We therefore force it always to
1191 be treated as local. */
1192
1193 if (h->address != NULL)
1194 {
1195 ip_address_item *ip;
1196 if (Ustrcmp(h->address, "0.0.0.0") == 0) goto FOUND_LOCAL;
1197 for (ip = local_interface_data; ip != NULL; ip = ip->next)
1198 if (Ustrcmp(h->address, ip->address) == 0) goto FOUND_LOCAL;
1199 yield = HOST_FOUND; /* At least one remote address has been found */
1200 }
1201
1202 /* Update prev to point to the last host item before any that have
1203 the same MX value as the one we have just considered. */
1204
1205 if (h->next == NULL || h->next->mx != h->mx) prev = h;
1206 }
1207
1208return yield; /* No local hosts found: return HOST_FOUND or HOST_FIND_FAILED */
1209
1210/* A host whose IP address matches a local IP address, or whose name matches
1211something in hosts_treat_as_local has been found. */
1212
1213FOUND_LOCAL:
1214
1215if (prev == NULL)
1216 {
1217 HDEBUG(D_host_lookup) debug_printf((h->mx >= 0)?
1218 "local host has lowest MX\n" :
1219 "local host found for non-MX address\n");
1220 return HOST_FOUND_LOCAL;
1221 }
1222
1223HDEBUG(D_host_lookup)
1224 {
1225 debug_printf("local host in host list - removed hosts:\n");
1226 for (h = prev->next; h != last->next; h = h->next)
1227 debug_printf(" %s %s %d\n", h->name, h->address, h->mx);
1228 }
1229
1230if (removed != NULL) *removed = TRUE;
1231prev->next = last->next;
1232*lastptr = prev;
1233return yield;
1234}
1235
1236
1237
1238
1239/*************************************************
1240* Remove duplicate IPs in host list *
1241*************************************************/
1242
1243/* You would think that administrators could set up their DNS records so that
1244one ended up with a list of unique IP addresses after looking up A or MX
1245records, but apparently duplication is common. So we scan such lists and
1246remove the later duplicates. Note that we may get lists in which some host
1247addresses are not set.
1248
1249Arguments:
1250 host pointer to the first host in the chain
1251 lastptr pointer to pointer to the last host in the chain (may be updated)
1252
1253Returns: nothing
1254*/
1255
1256static void
1257host_remove_duplicates(host_item *host, host_item **lastptr)
1258{
1259while (host != *lastptr)
1260 {
1261 if (host->address != NULL)
1262 {
1263 host_item *h = host;
1264 while (h != *lastptr)
1265 {
1266 if (h->next->address != NULL &&
1267 Ustrcmp(h->next->address, host->address) == 0)
1268 {
1269 DEBUG(D_host_lookup) debug_printf("duplicate IP address %s (MX=%d) "
1270 "removed\n", host->address, h->next->mx);
1271 if (h->next == *lastptr) *lastptr = h;
1272 h->next = h->next->next;
1273 }
1274 else h = h->next;
1275 }
1276 }
1277 /* If the last item was removed, host may have become == *lastptr */
1278 if (host != *lastptr) host = host->next;
1279 }
1280}
1281
1282
1283
1284
1285/*************************************************
1286* Find sender host name by gethostbyaddr() *
1287*************************************************/
1288
1289/* This used to be the only way it was done, but it turns out that not all
1290systems give aliases for calls to gethostbyaddr() - or one of the modern
1291equivalents like getipnodebyaddr(). Fortunately, multiple PTR records are rare,
1292but they can still exist. This function is now used only when a DNS lookup of
1293the IP address fails, in order to give access to /etc/hosts.
1294
1295Arguments: none
1296Returns: OK, DEFER, FAIL
1297*/
1298
1299static int
1300host_name_lookup_byaddr(void)
1301{
1302int len;
1303uschar *s, *t;
1304struct hostent *hosts;
1305struct in_addr addr;
1306
1307/* Lookup on IPv6 system */
1308
1309#if HAVE_IPV6
1310if (Ustrchr(sender_host_address, ':') != NULL)
1311 {
1312 struct in6_addr addr6;
1313 if (inet_pton(AF_INET6, CS sender_host_address, &addr6) != 1)
1314 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "unable to parse \"%s\" as an "
1315 "IPv6 address", sender_host_address);
1316 #if HAVE_GETIPNODEBYADDR
1317 hosts = getipnodebyaddr(CS &addr6, sizeof(addr6), AF_INET6, &h_errno);
1318 #else
1319 hosts = gethostbyaddr(CS &addr6, sizeof(addr6), AF_INET6);
1320 #endif
1321 }
1322else
1323 {
1324 if (inet_pton(AF_INET, CS sender_host_address, &addr) != 1)
1325 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "unable to parse \"%s\" as an "
1326 "IPv4 address", sender_host_address);
1327 #if HAVE_GETIPNODEBYADDR
1328 hosts = getipnodebyaddr(CS &addr, sizeof(addr), AF_INET, &h_errno);
1329 #else
1330 hosts = gethostbyaddr(CS &addr, sizeof(addr), AF_INET);
1331 #endif
1332 }
1333
1334/* Do lookup on IPv4 system */
1335
1336#else
1337addr.s_addr = (S_ADDR_TYPE)inet_addr(CS sender_host_address);
1338hosts = gethostbyaddr(CS(&addr), sizeof(addr), AF_INET);
1339#endif
1340
1341/* Failed to look up the host. */
1342
1343if (hosts == NULL)
1344 {
1345 HDEBUG(D_host_lookup) debug_printf("IP address lookup failed: h_errno=%d\n",
1346 h_errno);
1347 return (h_errno == TRY_AGAIN || h_errno == NO_RECOVERY) ? DEFER : FAIL;
1348 }
1349
1350/* It seems there are some records in the DNS that yield an empty name. We
1351treat this as non-existent. In some operating systems, this is returned as an
1352empty string; in others as a single dot. */
1353
1354if (hosts->h_name[0] == 0 || hosts->h_name[0] == '.')
1355 {
1356 HDEBUG(D_host_lookup) debug_printf("IP address lookup yielded an empty name: "
1357 "treated as non-existent host name\n");
1358 return FAIL;
1359 }
1360
1361/* Copy and lowercase the name, which is in static storage in many systems.
1362Put it in permanent memory. */
1363
1364s = (uschar *)hosts->h_name;
1365len = Ustrlen(s) + 1;
1366t = sender_host_name = store_get_perm(len);
1367while (*s != 0) *t++ = tolower(*s++);
1368*t = 0;
1369
1370/* If the host has aliases, build a copy of the alias list */
1371
1372if (hosts->h_aliases != NULL)
1373 {
1374 int count = 1;
1375 uschar **aliases, **ptr;
1376 for (aliases = USS hosts->h_aliases; *aliases != NULL; aliases++) count++;
1377 ptr = sender_host_aliases = store_get_perm(count * sizeof(uschar *));
1378 for (aliases = USS hosts->h_aliases; *aliases != NULL; aliases++)
1379 {
1380 uschar *s = *aliases;
1381 int len = Ustrlen(s) + 1;
1382 uschar *t = *ptr++ = store_get_perm(len);
1383 while (*s != 0) *t++ = tolower(*s++);
1384 *t = 0;
1385 }
1386 *ptr = NULL;
1387 }
1388
1389return OK;
1390}
1391
1392
1393
1394/*************************************************
1395* Find host name for incoming call *
1396*************************************************/
1397
1398/* Put the name in permanent store, pointed to by sender_host_name. We also set
1399up a list of alias names, pointed to by sender_host_alias. The list is
1400NULL-terminated. The incoming address is in sender_host_address, either in
1401dotted-quad form for IPv4 or in colon-separated form for IPv6.
1402
1403This function does a thorough check that the names it finds point back to the
1404incoming IP address. Any that do not are discarded. Note that this is relied on
1405by the ACL reverse_host_lookup check.
1406
1407On some systems, get{host,ipnode}byaddr() appears to do this internally, but
1408this it not universally true. Also, for release 4.30, this function was changed
1409to do a direct DNS lookup first, by default[1], because it turns out that that
1410is the only guaranteed way to find all the aliases on some systems. My
1411experiments indicate that Solaris gethostbyaddr() gives the aliases for but
1412Linux does not.
1413
1414[1] The actual order is controlled by the host_lookup_order option.
1415
1416Arguments: none
1417Returns: OK on success, the answer being placed in the global variable
1418 sender_host_name, with any aliases in a list hung off
1419 sender_host_aliases
1420 FAIL if no host name can be found
1421 DEFER if a temporary error was encountered
1422
1423The variable host_lookup_msg is set to an empty string on sucess, or to a
1424reason for the failure otherwise, in a form suitable for tagging onto an error
8e669ac1 1425message, and also host_lookup_failed is set TRUE if the lookup failed. If there
b08b24c8
PH
1426was a defer, host_lookup_deferred is set TRUE.
1427
1428Any dynamically constructed string for host_lookup_msg must be in permanent
1429store, because it might be used for several incoming messages on the same SMTP
059ec3d9
PH
1430connection. */
1431
1432int
1433host_name_lookup(void)
1434{
1435int old_pool, rc;
1436int sep = 0;
1437uschar *hname, *save_hostname;
1438uschar **aliases;
1439uschar buffer[256];
1440uschar *ordername;
1441uschar *list = host_lookup_order;
1442dns_record *rr;
1443dns_answer dnsa;
1444dns_scan dnss;
1445
b08b24c8
PH
1446host_lookup_deferred = host_lookup_failed = FALSE;
1447
059ec3d9
PH
1448HDEBUG(D_host_lookup)
1449 debug_printf("looking up host name for %s\n", sender_host_address);
1450
1451/* For testing the case when a lookup does not complete, we have a special
1452reserved IP address. */
1453
1454if (running_in_test_harness &&
1455 Ustrcmp(sender_host_address, "99.99.99.99") == 0)
1456 {
1457 HDEBUG(D_host_lookup)
1458 debug_printf("Test harness: host name lookup returns DEFER\n");
8e669ac1 1459 host_lookup_deferred = TRUE;
059ec3d9
PH
1460 return DEFER;
1461 }
1462
1463/* Do lookups directly in the DNS or via gethostbyaddr() (or equivalent), in
1464the order specified by the host_lookup_order option. */
1465
1466while ((ordername = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))
1467 != NULL)
1468 {
1469 if (strcmpic(ordername, US"bydns") == 0)
1470 {
1471 dns_init(FALSE, FALSE);
1472 dns_build_reverse(sender_host_address, buffer);
1473 rc = dns_lookup(&dnsa, buffer, T_PTR, NULL);
1474
1475 /* The first record we come across is used for the name; others are
1476 considered to be aliases. We have to scan twice, in order to find out the
1477 number of aliases. However, if all the names are empty, we will behave as
1478 if failure. (PTR records that yield empty names have been encountered in
1479 the DNS.) */
1480
1481 if (rc == DNS_SUCCEED)
1482 {
1483 uschar **aptr = NULL;
1484 int ssize = 264;
1485 int count = 0;
1486 int old_pool = store_pool;
1487
1488 store_pool = POOL_PERM; /* Save names in permanent storage */
1489
1490 for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
1491 rr != NULL;
1492 rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
1493 {
1494 if (rr->type == T_PTR) count++;
1495 }
1496
1497 /* Get store for the list of aliases. For compatibility with
1498 gethostbyaddr, we make an empty list if there are none. */
1499
1500 aptr = sender_host_aliases = store_get(count * sizeof(uschar *));
1501
1502 /* Re-scan and extract the names */
1503
1504 for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
1505 rr != NULL;
1506 rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
1507 {
1508 uschar *s = NULL;
1509 if (rr->type != T_PTR) continue;
1510 s = store_get(ssize);
1511
1512 /* If an overlong response was received, the data will have been
1513 truncated and dn_expand may fail. */
1514
1515 if (dn_expand(dnsa.answer, dnsa.answer + dnsa.answerlen,
1516 (uschar *)(rr->data), (DN_EXPAND_ARG4_TYPE)(s), ssize) < 0)
1517 {
1518 log_write(0, LOG_MAIN, "host name alias list truncated for %s",
1519 sender_host_address);
1520 break;
1521 }
1522
1523 store_reset(s + Ustrlen(s) + 1);
1524 if (s[0] == 0)
1525 {
1526 HDEBUG(D_host_lookup) debug_printf("IP address lookup yielded an "
1527 "empty name: treated as non-existent host name\n");
1528 continue;
1529 }
1530 if (sender_host_name == NULL) sender_host_name = s;
1531 else *aptr++ = s;
1532 while (*s != 0) { *s = tolower(*s); s++; }
1533 }
1534
1535 *aptr = NULL; /* End of alias list */
1536 store_pool = old_pool; /* Reset store pool */
1537
1538 /* If we've found a names, break out of the "order" loop */
1539
1540 if (sender_host_name != NULL) break;
1541 }
1542
1543 /* If the DNS lookup deferred, we must also defer. */
1544
1545 if (rc == DNS_AGAIN)
1546 {
1547 HDEBUG(D_host_lookup)
1548 debug_printf("IP address PTR lookup gave temporary error\n");
8e669ac1 1549 host_lookup_deferred = TRUE;
059ec3d9
PH
1550 return DEFER;
1551 }
1552 }
1553
1554 /* Do a lookup using gethostbyaddr() - or equivalent */
1555
1556 else if (strcmpic(ordername, US"byaddr") == 0)
1557 {
1558 HDEBUG(D_host_lookup)
1559 debug_printf("IP address lookup using gethostbyaddr()\n");
059ec3d9 1560 rc = host_name_lookup_byaddr();
8e669ac1 1561 if (rc == DEFER)
b08b24c8 1562 {
8e669ac1 1563 host_lookup_deferred = TRUE;
b08b24c8 1564 return rc; /* Can't carry on */
8e669ac1 1565 }
059ec3d9
PH
1566 if (rc == OK) break; /* Found a name */
1567 }
1568 } /* Loop for bydns/byaddr scanning */
1569
1570/* If we have failed to find a name, return FAIL and log when required.
1571NB host_lookup_msg must be in permanent store. */
1572
1573if (sender_host_name == NULL)
1574 {
1575 if (host_checking || !log_testing_mode)
1576 log_write(L_host_lookup_failed, LOG_MAIN, "no host name found for IP "
1577 "address %s", sender_host_address);
1578 host_lookup_msg = US" (failed to find host name from IP address)";
b08b24c8 1579 host_lookup_failed = TRUE;
059ec3d9
PH
1580 return FAIL;
1581 }
1582
1583/* We have a host name. If we are running in the test harness, we want the host
1584name and its alias to appear always the same way round. There are only ever two
1585names in these tests. If one of them contains "alias", make sure it is second;
1586otherwise put them in alphabetical order. */
1587
1588if (running_in_test_harness && *sender_host_aliases != NULL &&
1589 (
1590 Ustrstr(sender_host_name, "alias") != NULL ||
1591 (
1592 Ustrstr(*sender_host_aliases, "alias") == NULL &&
1593 Ustrcmp(sender_host_name, *sender_host_aliases) > 0
1594 )
1595 ))
1596 {
1597 uschar *temp = sender_host_name;
1598 sender_host_name = *sender_host_aliases;
1599 *sender_host_aliases = temp;
1600 }
1601
1602/* Debug output what was found, after test harness swapping, for consistency */
1603
1604HDEBUG(D_host_lookup)
1605 {
1606 uschar **aliases = sender_host_aliases;
1607 debug_printf("IP address lookup yielded %s\n", sender_host_name);
1608 while (*aliases != NULL) debug_printf(" alias %s\n", *aliases++);
1609 }
1610
1611/* We need to verify that a forward lookup on the name we found does indeed
1612correspond to the address. This is for security: in principle a malefactor who
1613happened to own a reverse zone could set it to point to any names at all.
1614
1615This code was present in versions of Exim before 3.20. At that point I took it
1616out because I thought that gethostbyaddr() did the check anyway. It turns out
1617that this isn't always the case, so it's coming back in at 4.01. This version
1618is actually better, because it also checks aliases.
1619
1620The code was made more robust at release 4.21. Prior to that, it accepted all
1621the names if any of them had the correct IP address. Now the code checks all
1622the names, and accepts only those that have the correct IP address. */
1623
1624save_hostname = sender_host_name; /* Save for error messages */
1625aliases = sender_host_aliases;
1626for (hname = sender_host_name; hname != NULL; hname = *aliases++)
1627 {
1628 int rc;
1629 BOOL ok = FALSE;
1630 host_item h;
1631 h.next = NULL;
1632 h.name = hname;
1633 h.mx = MX_NONE;
1634 h.address = NULL;
1635
1636 /* When called with the 5th argument FALSE, host_find_byname() won't return
1637 HOST_FOUND_LOCAL. If the incoming address is an IPv4 address expressed in
1638 IPv6 format, we must compare the IPv4 part to any IPv4 addresses. */
1639
1640 if ((rc = host_find_byname(&h, NULL, NULL, FALSE)) == HOST_FOUND)
1641 {
1642 host_item *hh;
1643 uschar *address_ipv4 = (Ustrncmp(sender_host_address, "::ffff:", 7) == 0)?
1644 sender_host_address + 7 : sender_host_address;
1645 HDEBUG(D_host_lookup) debug_printf("checking addresses for %s\n", hname);
1646 for (hh = &h; hh != NULL; hh = hh->next)
1647 {
1648 if ((Ustrcmp(hh->address, (Ustrchr(hh->address, ':') == NULL)?
1649 address_ipv4 : sender_host_address)) == 0)
1650 {
1651 HDEBUG(D_host_lookup) debug_printf(" %s OK\n", hh->address);
1652 ok = TRUE;
1653 break;
1654 }
1655 else
1656 {
1657 HDEBUG(D_host_lookup) debug_printf(" %s\n", hh->address);
1658 }
1659 }
1660 if (!ok) HDEBUG(D_host_lookup)
1661 debug_printf("no IP address for %s matched %s\n", hname,
1662 sender_host_address);
1663 }
1664 else if (rc == HOST_FIND_AGAIN)
1665 {
1666 HDEBUG(D_host_lookup) debug_printf("temporary error for host name lookup\n");
8e669ac1 1667 host_lookup_deferred = TRUE;
059ec3d9
PH
1668 return DEFER;
1669 }
1670 else
1671 {
1672 HDEBUG(D_host_lookup) debug_printf("no IP addresses found for %s\n", hname);
1673 }
1674
1675 /* If this name is no good, and it's the sender name, set it null pro tem;
1676 if it's an alias, just remove it from the list. */
1677
1678 if (!ok)
1679 {
1680 if (hname == sender_host_name) sender_host_name = NULL; else
1681 {
1682 uschar **a; /* Don't amalgamate - some */
1683 a = --aliases; /* compilers grumble */
1684 while (*a != NULL) { *a = a[1]; a++; }
1685 }
1686 }
1687 }
1688
1689/* If sender_host_name == NULL, it means we didn't like the name. Replace
1690it with the first alias, if there is one. */
1691
1692if (sender_host_name == NULL && *sender_host_aliases != NULL)
1693 sender_host_name = *sender_host_aliases++;
1694
1695/* If we now have a main name, all is well. */
1696
1697if (sender_host_name != NULL) return OK;
1698
1699/* We have failed to find an address that matches. */
1700
1701HDEBUG(D_host_lookup)
1702 debug_printf("%s does not match any IP address for %s\n",
1703 sender_host_address, save_hostname);
1704
1705/* This message must be in permanent store */
1706
1707old_pool = store_pool;
1708store_pool = POOL_PERM;
1709host_lookup_msg = string_sprintf(" (%s does not match any IP address for %s)",
1710 sender_host_address, save_hostname);
1711store_pool = old_pool;
059ec3d9
PH
1712host_lookup_failed = TRUE;
1713return FAIL;
1714}
1715
1716
1717
1718
1719/*************************************************
1720* Find IP address(es) for host by name *
1721*************************************************/
1722
1723/* The input is a host_item structure with the name filled in and the address
1724field set to NULL. We use gethostbyname(). Of course, gethostbyname() may use
1725the DNS, but it doesn't do MX processing. If more than one address is given,
1726chain on additional host items, with other relevant fields copied.
1727
1728The second argument provides a host list (usually an IP list) of hosts to
1729ignore. This makes it possible to ignore IPv6 link-local addresses or loopback
1730addresses in unreasonable places.
1731
1732The lookup may result in a change of name. For compatibility with the dns
1733lookup, return this via fully_qualified_name as well as updating the host item.
1734The lookup may also yield more than one IP address, in which case chain on
1735subsequent host_item structures.
1736
1737Arguments:
1738 host a host item with the name and MX filled in;
1739 the address is to be filled in;
1740 multiple IP addresses cause other host items to be
1741 chained on.
1742 ignore_target_hosts a list of hosts to ignore
1743 fully_qualified_name if not NULL, set to point to host name for
1744 compatibility with host_find_bydns
1745 local_host_check TRUE if a check for the local host is wanted
1746
1747Returns: HOST_FIND_FAILED Failed to find the host or domain
1748 HOST_FIND_AGAIN Try again later
1749 HOST_FOUND Host found - data filled in
1750 HOST_FOUND_LOCAL Host found and is the local host
1751*/
1752
1753int
1754host_find_byname(host_item *host, uschar *ignore_target_hosts,
1755 uschar **fully_qualified_name, BOOL local_host_check)
1756{
1757int i, yield, times;
1758uschar **addrlist;
1759host_item *last = NULL;
1760BOOL temp_error = FALSE;
b08b24c8
PH
1761#if HAVE_IPV6
1762int af;
1763#endif
1764
1765/* If we are in the test harness, a name ending in .test.again.dns always
1766forces a temporary error response. */
1767
1768if (running_in_test_harness)
1769 {
1770 uschar *endname = host->name + Ustrlen(host->name);
1771 if (Ustrcmp(endname - 14, "test.again.dns") == 0)
1772 return HOST_FIND_AGAIN;
8e669ac1 1773 }
059ec3d9
PH
1774
1775/* In an IPv6 world, we need to scan for both kinds of address, so go round the
1776loop twice. Note that we have ensured that AF_INET6 is defined even in an IPv4
1777world, which makes for slightly tidier code. However, if dns_ipv4_lookup
1778matches the domain, we also just do IPv4 lookups here (except when testing
1779standalone). */
1780
1781#if HAVE_IPV6
059ec3d9
PH
1782 #ifndef STAND_ALONE
1783 if (dns_ipv4_lookup != NULL &&
1784 match_isinlist(host->name, &dns_ipv4_lookup, 0, NULL, NULL, MCL_DOMAIN,
1785 TRUE, NULL) == OK)
1786 { af = AF_INET; times = 1; }
1787 else
1788 #endif /* STAND_ALONE */
1789
1790 { af = AF_INET6; times = 2; }
1791
1792/* No IPv6 support */
1793
1794#else /* HAVE_IPV6 */
1795 times = 1;
1796#endif /* HAVE_IPV6 */
1797
1798/* Initialize the flag that gets set for DNS syntax check errors, so that the
1799interface to this function can be similar to host_find_bydns. */
1800
1801host_find_failed_syntax = FALSE;
1802
1803/* Loop to look up both kinds of address in an IPv6 world */
1804
1805for (i = 1; i <= times;
1806 #if HAVE_IPV6
1807 af = AF_INET, /* If 2 passes, IPv4 on the second */
1808 #endif
1809 i++)
1810 {
1811 BOOL ipv4_addr;
1812 int error_num;
1813 struct hostent *hostdata;
1814
1815 #if HAVE_IPV6
1816 #if HAVE_GETIPNODEBYNAME
1817 hostdata = getipnodebyname(CS host->name, af, 0, &error_num);
1818 #else
1819 hostdata = gethostbyname2(CS host->name, af);
1820 error_num = h_errno;
1821 #endif
1822 #else
1823 hostdata = gethostbyname(CS host->name);
1824 error_num = h_errno;
1825 #endif
1826
1827 if (hostdata == NULL)
1828 {
1829 uschar *error;
1830 switch (error_num)
1831 {
1832 case HOST_NOT_FOUND: error = US"HOST_NOT_FOUND"; break;
1833 case TRY_AGAIN: error = US"TRY_AGAIN"; break;
1834 case NO_RECOVERY: error = US"NO_RECOVERY"; break;
1835 case NO_DATA: error = US"NO_DATA"; break;
1836 #if NO_DATA != NO_ADDRESS
1837 case NO_ADDRESS: error = US"NO_ADDRESS"; break;
1838 #endif
1839 default: error = US"?"; break;
1840 }
1841
1842 DEBUG(D_host_lookup) debug_printf("%s returned %d (%s)\n",
1843 #if HAVE_IPV6
1844 #if HAVE_GETIPNODEBYNAME
1845 (af == AF_INET6)? "getipnodebyname(af=inet6)" : "getipnodebyname(af=inet)",
1846 #else
1847 (af == AF_INET6)? "gethostbyname2(af=inet6)" : "gethostbyname2(af=inet)",
1848 #endif
1849 #else
1850 "gethostbyname",
1851 #endif
1852 error_num, error);
1853
1854 if (error_num == TRY_AGAIN || error_num == NO_RECOVERY) temp_error = TRUE;
1855 continue;
1856 }
1857 if ((hostdata->h_addr_list)[0] == NULL) continue;
1858
1859 /* Replace the name with the fully qualified one if necessary, and fill in
1860 the fully_qualified_name pointer. */
1861
1862 if (hostdata->h_name[0] != 0 &&
1863 Ustrcmp(host->name, hostdata->h_name) != 0)
1864 host->name = string_copy_dnsdomain((uschar *)hostdata->h_name);
1865 if (fully_qualified_name != NULL) *fully_qualified_name = host->name;
1866
1867 /* Get the list of addresses. IPv4 and IPv6 addresses can be distinguished
1868 by their different lengths. Scan the list, ignoring any that are to be
1869 ignored, and build a chain from the rest. */
1870
1871 ipv4_addr = hostdata->h_length == sizeof(struct in_addr);
1872
1873 for (addrlist = USS hostdata->h_addr_list; *addrlist != NULL; addrlist++)
1874 {
1875 uschar *text_address =
1876 host_ntoa(ipv4_addr? AF_INET:AF_INET6, *addrlist, NULL, NULL);
1877
1878 #ifndef STAND_ALONE
1879 if (ignore_target_hosts != NULL &&
1880 verify_check_this_host(&ignore_target_hosts, NULL, host->name,
1881 text_address, NULL) == OK)
1882 {
1883 DEBUG(D_host_lookup)
1884 debug_printf("ignored host %s [%s]\n", host->name, text_address);
1885 continue;
1886 }
1887 #endif
1888
1889 /* If this is the first address, last == NULL and we put the data in the
1890 original block. */
1891
1892 if (last == NULL)
1893 {
1894 host->address = text_address;
1895 host->port = PORT_NONE;
1896 host->status = hstatus_unknown;
1897 host->why = hwhy_unknown;
1898 last = host;
1899 }
1900
1901 /* Else add further host item blocks for any other addresses, keeping
1902 the order. */
1903
1904 else
1905 {
1906 host_item *next = store_get(sizeof(host_item));
1907 next->name = host->name;
1908 next->mx = host->mx;
1909 next->address = text_address;
1910 next->port = PORT_NONE;
1911 next->status = hstatus_unknown;
1912 next->why = hwhy_unknown;
1913 next->last_try = 0;
1914 next->next = last->next;
1915 last->next = next;
1916 last = next;
1917 }
1918 }
1919 }
1920
1921/* If no hosts were found, the address field in the original host block will be
1922NULL. If temp_error is set, at least one of the lookups gave a temporary error,
1923so we pass that back. */
1924
1925if (host->address == NULL)
1926 {
1927 uschar *msg =
1928 #ifndef STAND_ALONE
1929 (message_id[0] == 0 && smtp_in != NULL)?
1930 string_sprintf("no IP address found for host %s (during %s)", host->name,
1931 smtp_get_connection_info()) :
1932 #endif
1933 string_sprintf("no IP address found for host %s", host->name);
1934
1935 HDEBUG(D_host_lookup) debug_printf("%s\n", msg);
1936 if (temp_error) return HOST_FIND_AGAIN;
1937 if (host_checking || !log_testing_mode)
1938 log_write(L_host_lookup_failed, LOG_MAIN, "%s", msg);
1939 return HOST_FIND_FAILED;
1940 }
1941
1942/* Remove any duplicate IP addresses, then check to see if this is the local
1943host if required. */
1944
1945host_remove_duplicates(host, &last);
1946yield = local_host_check?
1947 host_scan_for_local_hosts(host, &last, NULL) : HOST_FOUND;
1948
1949/* When running in the test harness, sort into the order of addresses so as to
d8ef3577 1950get repeatability. */
059ec3d9 1951
d8ef3577 1952if (running_in_test_harness) sort_addresses(host, last);
059ec3d9
PH
1953
1954HDEBUG(D_host_lookup)
1955 {
1956 host_item *h;
1957 if (fully_qualified_name != NULL)
1958 debug_printf("fully qualified name = %s\n", *fully_qualified_name);
1959 debug_printf("%s looked up these IP addresses:\n",
1960 #if HAVE_IPV6
1961 #if HAVE_GETIPNODEBYNAME
1962 "getipnodebyname"
1963 #else
1964 "gethostbyname2"
1965 #endif
1966 #else
1967 "gethostbyname"
1968 #endif
1969 );
1970 for (h = host; h != last->next; h = h->next)
1971 debug_printf(" name=%s address=%s\n", h->name,
1972 (h->address == NULL)? US"<null>" : h->address);
1973 }
1974
1975/* Return the found status. */
1976
1977return yield;
1978}
1979
1980
1981
1982/*************************************************
1983* Fill in a host address from the DNS *
1984*************************************************/
1985
1986/* Given a host item, with its name and mx fields set, and its address field
1987set to NULL, fill in its IP address from the DNS. If it is multi-homed, create
1988additional host items for the additional addresses, copying all the other
1989fields, and randomizing the order.
1990
1991On IPv6 systems, A6 records are sought first (but only if support for A6 is
1992configured - they may never become mainstream), then AAAA records are sought,
1993and finally A records are sought as well.
1994
1995The host name may be changed if the DNS returns a different name - e.g. fully
1996qualified or changed via CNAME. If fully_qualified_name is not NULL, dns_lookup
1997ensures that it points to the fully qualified name. However, this is the fully
1998qualified version of the original name; if a CNAME is involved, the actual
1999canonical host name may be different again, and so we get it directly from the
2000relevant RR. Note that we do NOT change the mx field of the host item in this
2001function as it may be called to set the addresses of hosts taken from MX
2002records.
2003
2004Arguments:
2005 host points to the host item we're filling in
2006 lastptr points to pointer to last host item in a chain of
2007 host items (may be updated if host is last and gets
2008 extended because multihomed)
2009 ignore_target_hosts list of hosts to ignore
2010 allow_ip if TRUE, recognize an IP address and return it
2011 fully_qualified_name if not NULL, return fully qualified name here if
2012 the contents are different (i.e. it must be preset
2013 to something)
2014
2015Returns: HOST_FIND_FAILED couldn't find A record
2016 HOST_FIND_AGAIN try again later
2017 HOST_FOUND found AAAA and/or A record(s)
2018 HOST_IGNORED found, but all IPs ignored
2019*/
2020
2021static int
2022set_address_from_dns(host_item *host, host_item **lastptr,
2023 uschar *ignore_target_hosts, BOOL allow_ip, uschar **fully_qualified_name)
2024{
2025dns_record *rr;
2026host_item *thishostlast = NULL; /* Indicates not yet filled in anything */
2027BOOL v6_find_again = FALSE;
2028int i;
2029
2030/* If allow_ip is set, a name which is an IP address returns that value
2031as its address. This is used for MX records when allow_mx_to_ip is set, for
2032those sites that feel they have to flaunt the RFC rules. */
2033
2034if (allow_ip && string_is_ip_address(host->name, NULL) != 0)
2035 {
2036 #ifndef STAND_ALONE
2037 if (ignore_target_hosts != NULL &&
2038 verify_check_this_host(&ignore_target_hosts, NULL, host->name,
2039 host->name, NULL) == OK)
2040 return HOST_IGNORED;
2041 #endif
2042
2043 host->address = host->name;
2044 host->port = PORT_NONE;
2045 return HOST_FOUND;
2046 }
2047
2048/* On an IPv6 system, go round the loop up to three times, looking for A6 and
2049AAAA records the first two times. However, unless doing standalone testing, we
2050force an IPv4 lookup if the domain matches dns_ipv4_lookup is set. Since A6
2051records look like being abandoned, support them only if explicitly configured
2052to do so. On an IPv4 system, go round the loop once only, looking only for A
2053records. */
2054
2055#if HAVE_IPV6
2056
2057 #ifndef STAND_ALONE
2058 if (dns_ipv4_lookup != NULL &&
2059 match_isinlist(host->name, &dns_ipv4_lookup, 0, NULL, NULL, MCL_DOMAIN,
2060 TRUE, NULL) == OK)
2061 i = 0; /* look up A records only */
2062 else
2063 #endif /* STAND_ALONE */
2064
2065 #ifdef SUPPORT_A6
2066 i = 2; /* look up A6 and AAAA and A records */
2067 #else
2068 i = 1; /* look up AAAA and A records */
2069 #endif /* SUPPORT_A6 */
2070
2071/* The IPv4 world */
2072
2073#else /* HAVE_IPV6 */
2074 i = 0; /* look up A records only */
2075#endif /* HAVE_IPV6 */
2076
2077for (; i >= 0; i--)
2078 {
2079 static int types[] = { T_A, T_AAAA, T_A6 };
2080 int type = types[i];
2081 int randoffset = (i == 0)? 500 : 0; /* Ensures v6 sorts before v4 */
2082 dns_answer dnsa;
2083 dns_scan dnss;
2084
2085 int rc = dns_lookup(&dnsa, host->name, type, fully_qualified_name);
2086
2087 /* We want to return HOST_FIND_AGAIN if one of the A, A6, or AAAA lookups
2088 fails or times out, but not if another one succeeds. (In the early
2089 IPv6 days there are name servers that always fail on AAAA, but are happy
2090 to give out an A record. We want to proceed with that A record.) */
8e669ac1 2091
059ec3d9
PH
2092 if (rc != DNS_SUCCEED)
2093 {
2094 if (i == 0) /* Just tried for an A record, i.e. end of loop */
2095 {
2096 if (host->address != NULL) return HOST_FOUND; /* A6 or AAAA was found */
2097 if (rc == DNS_AGAIN || rc == DNS_FAIL || v6_find_again)
2098 return HOST_FIND_AGAIN;
2099 return HOST_FIND_FAILED; /* DNS_NOMATCH or DNS_NODATA */
2100 }
2101
2102 /* Tried for an A6 or AAAA record: remember if this was a temporary
2103 error, and look for the next record type. */
2104
2105 if (rc != DNS_NOMATCH && rc != DNS_NODATA) v6_find_again = TRUE;
2106 continue;
2107 }
2108
2109 /* Lookup succeeded: fill in the given host item with the first non-ignored
2110 address found; create additional items for any others. A single A6 record
2111 may generate more than one address. */
2112
2113 for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
2114 rr != NULL;
2115 rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
2116 {
2117 if (rr->type == type)
2118 {
2119 /* dns_address *da = dns_address_from_rr(&dnsa, rr); */
2120
2121 dns_address *da;
2122 da = dns_address_from_rr(&dnsa, rr);
2123
2124 DEBUG(D_host_lookup)
2125 {
2126 if (da == NULL)
2127 debug_printf("no addresses extracted from A6 RR for %s\n",
2128 host->name);
2129 }
2130
2131 /* This loop runs only once for A and AAAA records, but may run
2132 several times for an A6 record that generated multiple addresses. */
2133
2134 for (; da != NULL; da = da->next)
2135 {
2136 #ifndef STAND_ALONE
2137 if (ignore_target_hosts != NULL &&
2138 verify_check_this_host(&ignore_target_hosts, NULL,
2139 host->name, da->address, NULL) == OK)
2140 {
2141 DEBUG(D_host_lookup)
2142 debug_printf("ignored host %s [%s]\n", host->name, da->address);
2143 continue;
2144 }
2145 #endif
2146
2147 /* If this is the first address, stick it in the given host block,
2148 and change the name if the returned RR has a different name. */
2149
2150 if (thishostlast == NULL)
2151 {
2152 if (strcmpic(host->name, rr->name) != 0)
2153 host->name = string_copy_dnsdomain(rr->name);
2154 host->address = da->address;
2155 host->port = PORT_NONE;
2156 host->sort_key = host->mx * 1000 + random_number(500) + randoffset;
2157 host->status = hstatus_unknown;
2158 host->why = hwhy_unknown;
2159 thishostlast = host;
2160 }
2161
2162 /* Not the first address. Check for, and ignore, duplicates. Then
2163 insert in the chain at a random point. */
2164
2165 else
2166 {
2167 int new_sort_key;
2168 host_item *next;
2169
2170 /* End of our local chain is specified by "thishostlast". */
2171
2172 for (next = host;; next = next->next)
2173 {
2174 if (Ustrcmp(CS da->address, next->address) == 0) break;
2175 if (next == thishostlast) { next = NULL; break; }
2176 }
2177 if (next != NULL) continue; /* With loop for next address */
2178
2179 /* Not a duplicate */
2180
2181 new_sort_key = host->mx * 1000 + random_number(500) + randoffset;
2182 next = store_get(sizeof(host_item));
2183
2184 /* New address goes first: insert the new block after the first one
2185 (so as not to disturb the original pointer) but put the new address
2186 in the original block. */
2187
2188 if (new_sort_key < host->sort_key)
2189 {
2190 *next = *host;
2191 host->next = next;
2192 host->address = da->address;
2193 host->port = PORT_NONE;
2194 host->sort_key = new_sort_key;
2195 if (thishostlast == host) thishostlast = next; /* Local last */
2196 if (*lastptr == host) *lastptr = next; /* Global last */
2197 }
2198
2199 /* Otherwise scan down the addresses for this host to find the
2200 one to insert after. */
2201
2202 else
2203 {
2204 host_item *h = host;
2205 while (h != thishostlast)
2206 {
2207 if (new_sort_key < h->next->sort_key) break;
2208 h = h->next;
2209 }
2210 *next = *h;
2211 h->next = next;
2212 next->address = da->address;
2213 next->port = PORT_NONE;
2214 next->sort_key = new_sort_key;
2215 if (h == thishostlast) thishostlast = next; /* Local last */
2216 if (h == *lastptr) *lastptr = next; /* Global last */
2217 }
2218 }
2219 }
2220 }
2221 }
2222 }
2223
2224/* Control gets here only if the third lookup (the A record) succeeded.
2225However, the address may not be filled in if it was ignored. */
2226
2227return (host->address == NULL)? HOST_IGNORED : HOST_FOUND;
2228}
2229
2230
2231
2232
2233/*************************************************
2234* Find IP addresses and names for host via DNS *
2235*************************************************/
2236
2237/* The input is a host_item structure with the name filled in and the address
2238field set to NULL. This may be in a chain of other host items. The lookup may
2239result in more than one IP address, in which case we must created new host
2240blocks for the additional addresses, and insert them into the chain. The
2241original name may not be fully qualified. Use the fully_qualified_name argument
2242to return the official name, as returned by the resolver.
2243
2244Arguments:
2245 host point to initial host item
2246 ignore_target_hosts a list of hosts to ignore
2247 whichrrs flags indicating which RRs to look for:
2248 HOST_FIND_BY_SRV => look for SRV
2249 HOST_FIND_BY_MX => look for MX
2250 HOST_FIND_BY_A => look for A or AAAA
2251 also flags indicating how the lookup is done
2252 HOST_FIND_QUALIFY_SINGLE ) passed to the
2253 HOST_FIND_SEARCH_PARENTS ) resolver
2254 srv_service when SRV used, the service name
2255 srv_fail_domains DNS errors for these domains => assume nonexist
2256 mx_fail_domains DNS errors for these domains => assume nonexist
2257 fully_qualified_name if not NULL, return fully-qualified name
2258 removed set TRUE if local host was removed from the list
2259
2260Returns: HOST_FIND_FAILED Failed to find the host or domain;
2261 if there was a syntax error,
2262 host_find_failed_syntax is set.
2263 HOST_FIND_AGAIN Could not resolve at this time
2264 HOST_FOUND Host found
2265 HOST_FOUND_LOCAL The lowest MX record points to this
2266 machine, if MX records were found, or
2267 an A record that was found contains
2268 an address of the local host
2269*/
2270
2271int
2272host_find_bydns(host_item *host, uschar *ignore_target_hosts, int whichrrs,
2273 uschar *srv_service, uschar *srv_fail_domains, uschar *mx_fail_domains,
2274 uschar **fully_qualified_name, BOOL *removed)
2275{
2276host_item *h, *last;
2277dns_record *rr;
2278int rc = DNS_FAIL;
2279int ind_type = 0;
2280int yield;
2281dns_answer dnsa;
2282dns_scan dnss;
2283
2284/* Set the default fully qualified name to the incoming name, initialize the
2285resolver if necessary, set up the relevant options, and initialize the flag
2286that gets set for DNS syntax check errors. */
2287
2288if (fully_qualified_name != NULL) *fully_qualified_name = host->name;
2289dns_init((whichrrs & HOST_FIND_QUALIFY_SINGLE) != 0,
2290 (whichrrs & HOST_FIND_SEARCH_PARENTS) != 0);
2291host_find_failed_syntax = FALSE;
2292
2293/* First, if requested, look for SRV records. The service name is given; we
2294assume TCP progocol. DNS domain names are constrained to a maximum of 256
2295characters, so the code below should be safe. */
2296
2297if ((whichrrs & HOST_FIND_BY_SRV) != 0)
2298 {
2299 uschar buffer[300];
2300 uschar *temp_fully_qualified_name = buffer;
2301 int prefix_length;
2302
2303 (void)sprintf(CS buffer, "_%s._tcp.%n%.256s", srv_service, &prefix_length,
2304 host->name);
2305 ind_type = T_SRV;
2306
2307 /* Search for SRV records. If the fully qualified name is different to
2308 the input name, pass back the new original domain, without the prepended
2309 magic. */
2310
2311 rc = dns_lookup(&dnsa, buffer, ind_type, &temp_fully_qualified_name);
2312 if (temp_fully_qualified_name != buffer && fully_qualified_name != NULL)
2313 *fully_qualified_name = temp_fully_qualified_name + prefix_length;
2314
2315 /* On DNS failures, we give the "try again" error unless the domain is
2316 listed as one for which we continue. */
2317
2318 if (rc == DNS_FAIL || rc == DNS_AGAIN)
2319 {
2320 if (match_isinlist(host->name, &srv_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
2321 TRUE, NULL) != OK)
2322 return HOST_FIND_AGAIN;
2323 DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
2324 "(domain in srv_fail_domains)\n", (rc == DNS_FAIL)? "FAIL":"AGAIN");
2325 }
2326 }
2327
2328/* If we did not find any SRV records, search the DNS for MX records, if
2329requested to do so. If the result is DNS_NOMATCH, it means there is no such
2330domain, and there's no point in going on to look for address records with the
2331same domain. The result will be DNS_NODATA if the domain exists but has no MX
2332records. On DNS failures, we give the "try again" error unless the domain is
2333listed as one for which we continue. */
2334
2335if (rc != DNS_SUCCEED && (whichrrs & HOST_FIND_BY_MX) != 0)
2336 {
2337 ind_type = T_MX;
2338 rc = dns_lookup(&dnsa, host->name, ind_type, fully_qualified_name);
2339 if (rc == DNS_NOMATCH) return HOST_FIND_FAILED;
2340 if (rc == DNS_FAIL || rc == DNS_AGAIN)
2341 {
2342 if (match_isinlist(host->name, &mx_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
2343 TRUE, NULL) != OK)
2344 return HOST_FIND_AGAIN;
2345 DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
2346 "(domain in mx_fail_domains)\n", (rc == DNS_FAIL)? "FAIL":"AGAIN");
2347 }
2348 }
2349
2350/* If we haven't found anything yet, and we are requested to do so, try for an
2351A or AAAA record. If we find it (or them) check to see that it isn't the local
2352host. */
2353
2354if (rc != DNS_SUCCEED)
2355 {
2356 if ((whichrrs & HOST_FIND_BY_A) == 0)
2357 {
2358 DEBUG(D_host_lookup) debug_printf("Address records are not being sought\n");
2359 return HOST_FIND_FAILED;
2360 }
2361
2362 last = host; /* End of local chainlet */
2363 host->mx = MX_NONE;
2364 host->port = PORT_NONE;
2365 rc = set_address_from_dns(host, &last, ignore_target_hosts, FALSE,
2366 fully_qualified_name);
2367
2368 /* If one or more address records have been found, check that none of them
2369 are local. Since we know the host items all have their IP addresses
2370 inserted, host_scan_for_local_hosts() can only return HOST_FOUND or
2371 HOST_FOUND_LOCAL. We do not need to scan for duplicate IP addresses here,
2372 because set_address_from_dns() removes them. */
2373
2374 if (rc == HOST_FOUND)
2375 rc = host_scan_for_local_hosts(host, &last, removed);
2376 else
2377 if (rc == HOST_IGNORED) rc = HOST_FIND_FAILED; /* No special action */
2378
d8ef3577
PH
2379 /* When running in the test harness, sort into the order of addresses so as
2380 to get repeatability. */
8e669ac1 2381
d8ef3577
PH
2382 if (running_in_test_harness) sort_addresses(host, last);
2383
059ec3d9
PH
2384 DEBUG(D_host_lookup)
2385 {
2386 host_item *h;
2387 if (host->address != NULL)
2388 {
2389 if (fully_qualified_name != NULL)
2390 debug_printf("fully qualified name = %s\n", *fully_qualified_name);
2391 for (h = host; h != last->next; h = h->next)
2392 debug_printf("%s %s mx=%d sort=%d %s\n", h->name,
2393 (h->address == NULL)? US"<null>" : h->address, h->mx, h->sort_key,
2394 (h->status >= hstatus_unusable)? US"*" : US"");
2395 }
2396 }
2397
2398 return rc;
2399 }
2400
2401/* We have found one or more MX or SRV records. Sort them according to
2402precedence. Put the data for the first one into the existing host block, and
2403insert new host_item blocks into the chain for the remainder. For equal
2404precedences one is supposed to randomize the order. To make this happen, the
2405sorting is actually done on the MX value * 1000 + a random number. This is put
2406into a host field called sort_key.
2407
2408In the case of hosts with both IPv6 and IPv4 addresses, we want to choose the
2409IPv6 address in preference. At this stage, we don't know what kind of address
2410the host has. We choose a random number < 500; if later we find an A record
2411first, we add 500 to the random number. Then for any other address records, we
2412use random numbers in the range 0-499 for AAAA records and 500-999 for A
2413records.
2414
2415At this point we remove any duplicates that point to the same host, retaining
2416only the one with the lowest precedence. We cannot yet check for precedence
2417greater than that of the local host, because that test cannot be properly done
2418until the addresses have been found - an MX record may point to a name for this
2419host which is not the primary hostname. */
2420
2421last = NULL; /* Indicates that not even the first item is filled yet */
2422
2423for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
2424 rr != NULL;
2425 rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
2426 {
2427 int precedence;
2428 int weight = 0; /* For SRV records */
2429 int port = PORT_NONE; /* For SRV records */
2430 uschar *s; /* MUST be unsigned for GETSHORT */
2431 uschar data[256];
2432
2433 if (rr->type != ind_type) continue;
2434 s = rr->data;
2435 GETSHORT(precedence, s); /* Pointer s is advanced */
2436
2437 /* For MX records, we use a random "weight" which causes multiple records of
2438 the same precedence to sort randomly. */
2439
2440 if (ind_type == T_MX)
2441 {
2442 weight = random_number(500);
2443 }
2444
2445 /* SRV records are specified with a port and a weight. The weight is used
2446 in a special algorithm. However, to start with, we just use it to order the
2447 records of equal priority (precedence). */
2448
2449 else
2450 {
2451 GETSHORT(weight, s);
2452 GETSHORT(port, s);
2453 }
2454
2455 /* Get the name of the host pointed to. */
2456
2457 (void)dn_expand(dnsa.answer, dnsa.answer + dnsa.answerlen, s,
2458 (DN_EXPAND_ARG4_TYPE)data, sizeof(data));
2459
2460 /* Check that we haven't already got this host on the chain; if we have,
2461 keep only the lower precedence. This situation shouldn't occur, but you
2462 never know what junk might get into the DNS (and this case has been seen on
2463 more than one occasion). */
2464
2465 if (last != NULL) /* This is not the first record */
2466 {
2467 host_item *prev = NULL;
2468
2469 for (h = host; h != last->next; prev = h, h = h->next)
2470 {
2471 if (strcmpic(h->name, data) == 0)
2472 {
2473 DEBUG(D_host_lookup)
2474 debug_printf("discarded duplicate host %s (MX=%d)\n", data,
2475 (precedence > h->mx)? precedence : h->mx);
2476 if (precedence >= h->mx) goto NEXT_MX_RR; /* Skip greater precedence */
2477 if (h == host) /* Override first item */
2478 {
2479 h->mx = precedence;
2480 host->sort_key = precedence * 1000 + weight;
2481 goto NEXT_MX_RR;
2482 }
2483
2484 /* Unwanted host item is not the first in the chain, so we can get
2485 get rid of it by cutting it out. */
2486
2487 prev->next = h->next;
2488 if (h == last) last = prev;
2489 break;
2490 }
2491 }
2492 }
2493
2494 /* If this is the first MX or SRV record, put the data into the existing host
2495 block. Otherwise, add a new block in the correct place; if it has to be
2496 before the first block, copy the first block's data to a new second block. */
2497
2498 if (last == NULL)
2499 {
2500 host->name = string_copy_dnsdomain(data);
2501 host->address = NULL;
2502 host->port = port;
2503 host->mx = precedence;
2504 host->sort_key = precedence * 1000 + weight;
2505 host->status = hstatus_unknown;
2506 host->why = hwhy_unknown;
2507 last = host;
2508 }
2509
2510 /* Make a new host item and seek the correct insertion place */
2511
2512 else
2513 {
2514 int sort_key = precedence * 1000 + weight;
2515 host_item *next = store_get(sizeof(host_item));
2516 next->name = string_copy_dnsdomain(data);
2517 next->address = NULL;
2518 next->port = port;
2519 next->mx = precedence;
2520 next->sort_key = sort_key;
2521 next->status = hstatus_unknown;
2522 next->why = hwhy_unknown;
2523 next->last_try = 0;
2524
2525 /* Handle the case when we have to insert before the first item. */
2526
2527 if (sort_key < host->sort_key)
2528 {
2529 host_item htemp;
2530 htemp = *host;
2531 *host = *next;
2532 *next = htemp;
2533 host->next = next;
2534 if (last == host) last = next;
2535 }
2536
2537 /* Else scan down the items we have inserted as part of this exercise;
2538 don't go further. */
2539
2540 else
2541 {
2542 for (h = host; h != last; h = h->next)
2543 {
2544 if (sort_key < h->next->sort_key)
2545 {
2546 next->next = h->next;
2547 h->next = next;
2548 break;
2549 }
2550 }
2551
2552 /* Join on after the last host item that's part of this
2553 processing if we haven't stopped sooner. */
2554
2555 if (h == last)
2556 {
2557 next->next = last->next;
2558 last->next = next;
2559 last = next;
2560 }
2561 }
2562 }
2563
2564 NEXT_MX_RR: continue;
2565 }
2566
2567/* If the list of hosts was obtained from SRV records, there are two things to
2568do. First, if there is only one host, and it's name is ".", it means there is
2569no SMTP service at this domain. Otherwise, we have to sort the hosts of equal
2570priority according to their weights, using an algorithm that is defined in RFC
25712782. The hosts are currently sorted by priority and weight. For each priority
2572group we have to pick off one host and put it first, and then repeat for any
2573remaining in the same priority group. */
2574
2575if (ind_type == T_SRV)
2576 {
2577 host_item **pptr;
2578
2579 if (host == last && host->name[0] == 0)
2580 {
2581 DEBUG(D_host_lookup) debug_printf("the single SRV record is \".\"\n");
2582 return HOST_FIND_FAILED;
2583 }
2584
2585 DEBUG(D_host_lookup)
2586 {
2587 debug_printf("original ordering of hosts from SRV records:\n");
2588 for (h = host; h != last->next; h = h->next)
2589 debug_printf(" %s P=%d W=%d\n", h->name, h->mx, h->sort_key % 1000);
2590 }
2591
2592 for (pptr = &host, h = host; h != last; pptr = &(h->next), h = h->next)
2593 {
2594 int sum = 0;
2595 host_item *hh;
2596
2597 /* Find the last following host that has the same precedence. At the same
2598 time, compute the sum of the weights and the running totals. These can be
2599 stored in the sort_key field. */
2600
2601 for (hh = h; hh != last; hh = hh->next)
2602 {
2603 int weight = hh->sort_key % 1000; /* was precedence * 1000 + weight */
2604 sum += weight;
2605 hh->sort_key = sum;
2606 if (hh->mx != hh->next->mx) break;
2607 }
2608
2609 /* If there's more than one host at this precedence (priority), we need to
2610 pick one to go first. */
2611
2612 if (hh != h)
2613 {
2614 host_item *hhh;
2615 host_item **ppptr;
2616 int randomizer = random_number(sum + 1);
2617
2618 for (ppptr = pptr, hhh = h;
2619 hhh != hh;
2620 ppptr = &(hhh->next), hhh = hhh->next)
2621 {
2622 if (hhh->sort_key >= randomizer) break;
2623 }
2624
2625 /* hhh now points to the host that should go first; ppptr points to the
2626 place that points to it. Unfortunately, if the start of the minilist is
2627 the start of the entire list, we can't just swap the items over, because
2628 we must not change the value of host, since it is passed in from outside.
2629 One day, this could perhaps be changed.
2630
2631 The special case is fudged by putting the new item *second* in the chain,
2632 and then transferring the data between the first and second items. We
2633 can't just swap the first and the chosen item, because that would mean
2634 that an item with zero weight might no longer be first. */
2635
2636 if (hhh != h)
2637 {
2638 *ppptr = hhh->next; /* Cuts it out of the chain */
2639
2640 if (h == host)
2641 {
2642 host_item temp = *h;
2643 *h = *hhh;
2644 *hhh = temp;
2645 hhh->next = temp.next;
2646 h->next = hhh;
2647 }
2648
2649 else
2650 {
2651 hhh->next = h; /* The rest of the chain follows it */
2652 *pptr = hhh; /* It takes the place of h */
2653 h = hhh; /* It's now the start of this minilist */
2654 }
2655 }
2656 }
2657
2658 /* A host has been chosen to be first at this priority and h now points
2659 to this host. There may be others at the same priority, or others at a
2660 different priority. Before we leave this host, we need to put back a sort
2661 key of the traditional MX kind, in case this host is multihomed, because
2662 the sort key is used for ordering the multiple IP addresses. We do not need
2663 to ensure that these new sort keys actually reflect the order of the hosts,
2664 however. */
2665
2666 h->sort_key = h->mx * 1000 + random_number(500);
2667 } /* Move on to the next host */
2668 }
2669
2670/* Now we have to ensure addresses exist for all the hosts. We have ensured
2671above that the names in the host items are all unique. The addresses may have
2672been returned in the additional data section of the DNS query. Because it is
2673more expensive to scan the returned DNS records (because you have to expand the
2674names) we do a single scan over them, and multiple scans of the chain of host
2675items (which is typically only 3 or 4 long anyway.) Add extra host items for
2676multi-homed hosts. */
2677
2678for (rr = dns_next_rr(&dnsa, &dnss, RESET_ADDITIONAL);
2679 rr != NULL;
2680 rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
2681 {
2682 dns_address *da;
2683 int status = hstatus_unknown;
2684 int why = hwhy_unknown;
2685 int randoffset;
2686
2687 if (rr->type != T_A
2688 #if HAVE_IPV6
2689 && rr->type != T_AAAA
2690 #ifdef SUPPORT_A6
2691 && rr->type != T_A6
2692 #endif
2693 #endif
2694 ) continue;
2695
2696 /* Find the first host that matches this record's name. If there isn't
2697 one, move on to the next RR. */
2698
2699 for (h = host; h != last->next; h = h->next)
2700 { if (strcmpic(h->name, rr->name) == 0) break; }
2701 if (h == last->next) continue;
2702
2703 /* For IPv4 addresses, add 500 to the random part of the sort key, to ensure
2704 they sort after IPv6 addresses. */
2705
2706 randoffset = (rr->type == T_A)? 500 : 0;
2707
2708 /* Get the list of textual addresses for this RR. There may be more than one
2709 if it is an A6 RR. Then loop to handle multiple addresses from an A6 record.
2710 If there are none, nothing will get done - the record is ignored. */
2711
2712 for (da = dns_address_from_rr(&dnsa, rr); da != NULL; da = da->next)
2713 {
2714 /* Set status for an ignorable host. */
2715
2716 #ifndef STAND_ALONE
2717 if (ignore_target_hosts != NULL &&
2718 verify_check_this_host(&ignore_target_hosts, NULL, h->name,
2719 da->address, NULL) == OK)
2720 {
2721 DEBUG(D_host_lookup)
2722 debug_printf("ignored host %s [%s]\n", h->name, da->address);
2723 status = hstatus_unusable;
2724 why = hwhy_ignored;
2725 }
2726 #endif
2727
2728 /* If the address is already set for this host, it may be that
2729 we just have a duplicate DNS record. Alternatively, this may be
2730 a multi-homed host. Search all items with the same host name
2731 (they will all be together) and if this address is found, skip
2732 to the next RR. */
2733
2734 if (h->address != NULL)
2735 {
2736 int new_sort_key;
2737 host_item *thishostlast;
2738 host_item *hh = h;
2739
2740 do
2741 {
2742 if (hh->address != NULL && Ustrcmp(CS da->address, hh->address) == 0)
2743 goto DNS_NEXT_RR; /* Need goto to escape from inner loop */
2744 thishostlast = hh;
2745 hh = hh->next;
2746 }
2747 while (hh != last->next && strcmpic(hh->name, rr->name) == 0);
2748
2749 /* We have a multi-homed host, since we have a new address for
2750 an existing name. Create a copy of the current item, and give it
2751 the new address. RRs can be in arbitrary order, but one is supposed
2752 to randomize the addresses of multi-homed hosts, so compute a new
2753 sorting key and do that. [Latest SMTP RFC says not to randomize multi-
2754 homed hosts, but to rely on the resolver. I'm not happy about that -
2755 caching in the resolver will not rotate as often as the name server
2756 does.] */
2757
2758 new_sort_key = h->mx * 1000 + random_number(500) + randoffset;
2759 hh = store_get(sizeof(host_item));
2760
2761 /* New address goes first: insert the new block after the first one
2762 (so as not to disturb the original pointer) but put the new address
2763 in the original block. */
2764
2765 if (new_sort_key < h->sort_key)
2766 {
2767 *hh = *h; /* Note: copies the port */
2768 h->next = hh;
2769 h->address = da->address;
2770 h->sort_key = new_sort_key;
2771 h->status = status;
2772 h->why = why;
2773 }
2774
2775 /* Otherwise scan down the addresses for this host to find the
2776 one to insert after. */
2777
2778 else
2779 {
2780 while (h != thishostlast)
2781 {
2782 if (new_sort_key < h->next->sort_key) break;
2783 h = h->next;
2784 }
2785 *hh = *h; /* Note: copies the port */
2786 h->next = hh;
2787 hh->address = da->address;
2788 hh->sort_key = new_sort_key;
2789 hh->status = status;
2790 hh->why = why;
2791 }
2792
2793 if (h == last) last = hh; /* Inserted after last */
2794 }
2795
2796 /* The existing item doesn't have its address set yet, so just set it.
2797 Ensure that an IPv4 address gets its sort key incremented in case an IPv6
2798 address is found later. */
2799
2800 else
2801 {
2802 h->address = da->address; /* Port should be set already */
2803 h->status = status;
2804 h->why = why;
2805 h->sort_key += randoffset;
2806 }
2807 } /* Loop for addresses extracted from one RR */
2808
2809 /* Carry on to the next RR. It would be nice to be able to be able to stop
2810 when every host on the list has an address, but we can't be sure there won't
2811 be an additional address for a multi-homed host further down the list, so
2812 we have to continue to the end. */
2813
2814 DNS_NEXT_RR: continue;
2815 }
2816
2817/* Set the default yield to failure */
2818
2819yield = HOST_FIND_FAILED;
2820
2821/* If we haven't found all the addresses in the additional section, we
2822need to search for A or AAAA records explicitly. The names shouldn't point to
2823CNAMES, but we use the general lookup function that handles them, just
2824in case. If any lookup gives a soft error, change the default yield.
2825
2826For these DNS lookups, we must disable qualify_single and search_parents;
2827otherwise invalid host names obtained from MX or SRV records can cause trouble
2828if they happen to match something local. */
2829
2830dns_init(FALSE, FALSE);
2831
2832for (h = host; h != last->next; h = h->next)
2833 {
2834 if (h->address != NULL || h->status == hstatus_unusable) continue;
2835 rc = set_address_from_dns(h, &last, ignore_target_hosts, allow_mx_to_ip, NULL);
2836 if (rc != HOST_FOUND)
2837 {
2838 h->status = hstatus_unusable;
2839 if (rc == HOST_FIND_AGAIN)
2840 {
2841 yield = rc;
2842 h->why = hwhy_deferred;
2843 }
2844 else
2845 h->why = (rc == HOST_IGNORED)? hwhy_ignored : hwhy_failed;
2846 }
2847 }
2848
2849/* Scan the list for any hosts that are marked unusable because they have
2850been explicitly ignored, and remove them from the list, as if they did not
2851exist. If we end up with just a single, ignored host, flatten its fields as if
2852nothing was found. */
2853
2854if (ignore_target_hosts != NULL)
2855 {
2856 host_item *prev = NULL;
2857 for (h = host; h != last->next; h = h->next)
2858 {
2859 REDO:
2860 if (h->why != hwhy_ignored) /* Non ignored host, just continue */
2861 prev = h;
2862 else if (prev == NULL) /* First host is ignored */
2863 {
2864 if (h != last) /* First is not last */
2865 {
2866 if (h->next == last) last = h; /* Overwrite it with next */
2867 *h = *(h->next); /* and reprocess it. */
2868 goto REDO; /* C should have redo, like Perl */
2869 }
2870 }
2871 else /* Ignored host is not first - */
2872 { /* cut it out */
2873 prev->next = h->next;
2874 if (h == last) last = prev;
2875 }
2876 }
2877
2878 if (host->why == hwhy_ignored) host->address = NULL;
2879 }
2880
2881/* There is still one complication in the case of IPv6. Although the code above
2882arranges that IPv6 addresses take precedence over IPv4 addresses for multihomed
2883hosts, it doesn't do this for addresses that apply to different hosts with the
2884same MX precedence, because the sorting on MX precedence happens first. So we
2885have to make another pass to check for this case. We ensure that, within a
2886single MX preference value, IPv6 addresses come first. This can separate the
2887addresses of a multihomed host, but that should not matter. */
2888
2889#if HAVE_IPV6
2890if (h != last)
2891 {
2892 for (h = host; h != last; h = h->next)
2893 {
2894 host_item temp;
2895 host_item *next = h->next;
2896 if (h->mx != next->mx || /* If next is different MX value */
2897 (h->sort_key % 1000) < 500 || /* OR this one is IPv6 */
2898 (next->sort_key % 1000) >= 500) /* OR next is IPv4 */
2899 continue; /* move on to next */
2900 temp = *h;
2901 temp.next = next->next;
2902 *h = *next;
2903 h->next = next;
2904 *next = temp;
2905 }
2906 }
2907#endif
2908
2909/* When running in the test harness, we want the hosts always to be in the same
2910order so that the debugging output is the same and can be compared. Having a
2911fixed set of "random" numbers doesn't actually achieve this, because the RRs
2912come back from the resolver in a random order, so the non-random random numbers
2913get used in a different order. We therefore have to sort the hosts that have
2914the same MX values. We chose do to this by their name and then by IP address.
2915The fact that the sort is slow matters not - this is testing only! */
2916
2917if (running_in_test_harness)
2918 {
2919 BOOL done;
2920 do
2921 {
2922 done = TRUE;
2923 for (h = host; h != last; h = h->next)
2924 {
2925 int c = Ustrcmp(h->name, h->next->name);
2926 if (c == 0) c = Ustrcmp(h->address, h->next->address);
2927 if (h->mx == h->next->mx && c > 0)
2928 {
2929 host_item *next = h->next;
2930 host_item temp = *h;
2931 temp.next = next->next;
2932 *h = *next;
2933 h->next = next;
2934 *next = temp;
2935 done = FALSE;
2936 }
2937 }
2938 }
2939 while (!done);
2940 }
2941
2942/* Remove any duplicate IP addresses and then scan the list of hosts for any
2943whose IP addresses are on the local host. If any are found, all hosts with the
2944same or higher MX values are removed. However, if the local host has the lowest
2945numbered MX, then HOST_FOUND_LOCAL is returned. Otherwise, if at least one host
2946with an IP address is on the list, HOST_FOUND is returned. Otherwise,
2947HOST_FIND_FAILED is returned, but in this case do not update the yield, as it
2948might have been set to HOST_FIND_AGAIN just above here. If not, it will already
2949be HOST_FIND_FAILED. */
2950
2951host_remove_duplicates(host, &last);
2952rc = host_scan_for_local_hosts(host, &last, removed);
2953if (rc != HOST_FIND_FAILED) yield = rc;
2954
2955DEBUG(D_host_lookup)
2956 {
2957 if (fully_qualified_name != NULL)
2958 debug_printf("fully qualified name = %s\n", *fully_qualified_name);
2959 debug_printf("host_find_bydns yield = %s (%d); returned hosts:\n",
2960 (yield == HOST_FOUND)? "HOST_FOUND" :
2961 (yield == HOST_FOUND_LOCAL)? "HOST_FOUND_LOCAL" :
2962 (yield == HOST_FIND_AGAIN)? "HOST_FIND_AGAIN" :
2963 (yield == HOST_FIND_FAILED)? "HOST_FIND_FAILED" : "?",
2964 yield);
2965 for (h = host; h != last->next; h = h->next)
2966 {
2967 debug_printf(" %s %s MX=%d ", h->name,
2968 (h->address == NULL)? US"<null>" : h->address, h->mx);
2969 if (h->port != PORT_NONE) debug_printf("port=%d ", h->port);
2970 if (h->status >= hstatus_unusable) debug_printf("*");
2971 debug_printf("\n");
2972 }
2973 }
2974
2975return yield;
2976}
2977
2978
2979
2980
2981/*************************************************
2982**************************************************
2983* Stand-alone test program *
2984**************************************************
2985*************************************************/
2986
2987#ifdef STAND_ALONE
2988
2989BOOL alldigits(uschar *buffer)
2990{
2991if (!isdigit(*buffer)) return FALSE;
2992if (*buffer == '0' && buffer[1] == 'x')
2993 {
2994 buffer++;
2995 while (isxdigit(*(++buffer)));
2996 }
2997else while (isdigit(*(++buffer)));
2998return (*buffer == 0);
2999}
3000
3001int main(int argc, char **cargv)
3002{
3003host_item h;
3004int whichrrs = HOST_FIND_BY_MX | HOST_FIND_BY_A;
3005BOOL byname = FALSE;
3006BOOL qualify_single = TRUE;
3007BOOL search_parents = FALSE;
3008uschar **argv = USS cargv;
3009uschar buffer[256];
3010
3011primary_hostname = US"";
3012store_pool = POOL_MAIN;
3013debug_selector = D_host_lookup|D_interface;
3014debug_file = stdout;
3015debug_fd = fileno(debug_file);
3016
3017printf("Exim stand-alone host functions test\n");
3018
3019host_find_interfaces();
3020debug_selector = D_host_lookup | D_dns;
3021
3022if (argc > 1) primary_hostname = argv[1];
3023
3024/* So that debug level changes can be done first */
3025
3026dns_init(qualify_single, search_parents);
3027
3028printf("Testing host lookup\n");
3029printf("> ");
3030while (Ufgets(buffer, 256, stdin) != NULL)
3031 {
3032 int rc;
3033 int len = Ustrlen(buffer);
3034 uschar *fully_qualified_name;
3035
3036 while (len > 0 && isspace(buffer[len-1])) len--;
3037 buffer[len] = 0;
3038
3039 if (Ustrcmp(buffer, "q") == 0) break;
3040
3041 if (Ustrcmp(buffer, "byname") == 0) byname = TRUE;
3042 else if (Ustrcmp(buffer, "no_byname") == 0) byname = FALSE;
3043 else if (Ustrcmp(buffer, "a_only") == 0) whichrrs = HOST_FIND_BY_A;
3044 else if (Ustrcmp(buffer, "mx_only") == 0) whichrrs = HOST_FIND_BY_MX;
3045 else if (Ustrcmp(buffer, "srv_only") == 0) whichrrs = HOST_FIND_BY_SRV;
3046 else if (Ustrcmp(buffer, "srv+a") == 0)
3047 whichrrs = HOST_FIND_BY_SRV | HOST_FIND_BY_A;
3048 else if (Ustrcmp(buffer, "srv+mx") == 0)
3049 whichrrs = HOST_FIND_BY_SRV | HOST_FIND_BY_MX;
3050 else if (Ustrcmp(buffer, "srv+mx+a") == 0)
3051 whichrrs = HOST_FIND_BY_SRV | HOST_FIND_BY_MX | HOST_FIND_BY_A;
3052 else if (Ustrcmp(buffer, "qualify_single") == 0) qualify_single = TRUE;
3053 else if (Ustrcmp(buffer, "no_qualify_single") == 0) qualify_single = FALSE;
3054 else if (Ustrcmp(buffer, "search_parents") == 0) search_parents = TRUE;
3055 else if (Ustrcmp(buffer, "no_search_parents") == 0) search_parents = FALSE;
3056 else if (Ustrncmp(buffer, "retrans", 7) == 0)
3057 {
ff790e47 3058 (void)sscanf(CS(buffer+8), "%d", &dns_retrans);
059ec3d9
PH
3059 _res.retrans = dns_retrans;
3060 }
3061 else if (Ustrncmp(buffer, "retry", 5) == 0)
3062 {
ff790e47 3063 (void)sscanf(CS(buffer+6), "%d", &dns_retry);
059ec3d9
PH
3064 _res.retry = dns_retry;
3065 }
3066 else if (alldigits(buffer))
3067 {
3068 debug_selector = Ustrtol(buffer, NULL, 0);
3069 _res.options &= ~RES_DEBUG;
3070 DEBUG(D_resolver) _res.options |= RES_DEBUG;
3071 }
3072 else
3073 {
3074 int flags = whichrrs;
3075
3076 h.name = buffer;
3077 h.next = NULL;
3078 h.mx = MX_NONE;
3079 h.port = PORT_NONE;
3080 h.status = hstatus_unknown;
3081 h.why = hwhy_unknown;
3082 h.address = NULL;
3083
3084 if (qualify_single) flags |= HOST_FIND_QUALIFY_SINGLE;
3085 if (search_parents) flags |= HOST_FIND_SEARCH_PARENTS;
3086
3087 rc = byname?
3088 host_find_byname(&h, NULL, &fully_qualified_name, TRUE)
3089 :
3090 host_find_bydns(&h, NULL, flags, US"smtp", NULL, NULL,
3091 &fully_qualified_name, NULL);
3092
3093 if (rc == HOST_FIND_FAILED) printf("Failed\n");
3094 else if (rc == HOST_FIND_AGAIN) printf("Again\n");
3095 else if (rc == HOST_FOUND_LOCAL) printf("Local\n");
3096 }
3097
3098 printf("\n> ");
3099 }
3100
3101printf("Testing host_aton\n");
3102printf("> ");
3103while (Ufgets(buffer, 256, stdin) != NULL)
3104 {
3105 int i;
3106 int x[4];
3107 int len = Ustrlen(buffer);
3108
3109 while (len > 0 && isspace(buffer[len-1])) len--;
3110 buffer[len] = 0;
3111
3112 if (Ustrcmp(buffer, "q") == 0) break;
3113
3114 len = host_aton(buffer, x);
3115 printf("length = %d ", len);
3116 for (i = 0; i < len; i++)
3117 {
3118 printf("%04x ", (x[i] >> 16) & 0xffff);
3119 printf("%04x ", x[i] & 0xffff);
3120 }
3121 printf("\n> ");
3122 }
3123
3124printf("\n");
3125
3126printf("Testing host_name_lookup\n");
3127printf("> ");
3128while (Ufgets(buffer, 256, stdin) != NULL)
3129 {
3130 int len = Ustrlen(buffer);
3131 while (len > 0 && isspace(buffer[len-1])) len--;
3132 buffer[len] = 0;
3133 if (Ustrcmp(buffer, "q") == 0) break;
3134 sender_host_address = buffer;
3135 sender_host_name = NULL;
3136 sender_host_aliases = NULL;
3137 host_lookup_msg = US"";
3138 host_lookup_failed = FALSE;
3139 if (host_name_lookup() == FAIL) /* Debug causes printing */
3140 printf("Lookup failed:%s\n", host_lookup_msg);
3141 printf("\n> ");
3142 }
3143
3144printf("\n");
3145
3146return 0;
3147}
3148#endif /* STAND_ALONE */
3149
3150/* End of host.c */