Use dedicated union member for option offsets
[users/jgh/exim.git] / src / src / routers / dnslookup.c
index e4f7a2539335764ed1df37ebe0c75830ca07c657..7e074c23ed02bf90bf6740c1fbac4f2e751a35cf 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2015 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 #include "../exim.h"
 
 
 /* Options specific to the dnslookup router. */
+#define LOFF(field) OPT_OFF(dnslookup_router_options_block, field)
 
 optionlist dnslookup_router_options[] = {
-  { "check_secondary_mx", opt_bool,
-      (void *)(offsetof(dnslookup_router_options_block, check_secondary_mx)) },
-  { "check_srv",          opt_stringptr,
-      (void *)(offsetof(dnslookup_router_options_block, check_srv)) },
-  { "fail_defer_domains", opt_stringptr,
-      (void *)(offsetof(dnslookup_router_options_block, fail_defer_domains)) },
-  { "mx_domains",         opt_stringptr,
-      (void *)(offsetof(dnslookup_router_options_block, mx_domains)) },
-  { "mx_fail_domains",    opt_stringptr,
-      (void *)(offsetof(dnslookup_router_options_block, mx_fail_domains)) },
-  { "qualify_single",     opt_bool,
-      (void *)(offsetof(dnslookup_router_options_block, qualify_single)) },
-  { "rewrite_headers",    opt_bool,
-      (void *)(offsetof(dnslookup_router_options_block, rewrite_headers)) },
-  { "same_domain_copy_routing", opt_bool|opt_public,
-      (void *)(offsetof(router_instance, same_domain_copy_routing)) },
-  { "search_parents",     opt_bool,
-      (void *)(offsetof(dnslookup_router_options_block, search_parents)) },
-  { "srv_fail_domains",   opt_stringptr,
-      (void *)(offsetof(dnslookup_router_options_block, srv_fail_domains)) },
-  { "widen_domains",      opt_stringptr,
-      (void *)(offsetof(dnslookup_router_options_block, widen_domains)) }
+  { "check_secondary_mx", opt_bool,            LOFF(check_secondary_mx) },
+  { "check_srv",          opt_stringptr,       LOFF(check_srv) },
+  { "fail_defer_domains", opt_stringptr,       LOFF(fail_defer_domains) },
+  { "ipv4_only",          opt_stringptr,       LOFF(ipv4_only) },
+  { "ipv4_prefer",        opt_stringptr,       LOFF(ipv4_prefer) },
+  { "mx_domains",         opt_stringptr,       LOFF(mx_domains) },
+  { "mx_fail_domains",    opt_stringptr,       LOFF(mx_fail_domains) },
+  { "qualify_single",     opt_bool,            LOFF(qualify_single) },
+  { "rewrite_headers",    opt_bool,            LOFF(rewrite_headers) },
+  { "same_domain_copy_routing", opt_bool|opt_public, OPT_OFF(router_instance, same_domain_copy_routing) },
+  { "search_parents",     opt_bool,            LOFF(search_parents) },
+  { "srv_fail_domains",   opt_stringptr,       LOFF(srv_fail_domains) },
+  { "widen_domains",      opt_stringptr,       LOFF(widen_domains) }
 };
 
 /* Size of the options list. An extern variable has to be used so that its
@@ -44,19 +36,37 @@ address can appear in the tables drtables.c. */
 int dnslookup_router_options_count =
   sizeof(dnslookup_router_options)/sizeof(optionlist);
 
+
+#ifdef MACRO_PREDEF
+
+/* Dummy entries */
+dnslookup_router_options_block dnslookup_router_option_defaults = {0};
+void dnslookup_router_init(router_instance *rblock) {}
+int dnslookup_router_entry(router_instance *rblock, address_item *addr,
+  struct passwd *pw, int verify, address_item **addr_local,
+  address_item **addr_remote, address_item **addr_new,
+  address_item **addr_succeed) {return 0;}
+
+#else   /*!MACRO_PREDEF*/
+
+
+
+
 /* Default private options block for the dnslookup router. */
 
 dnslookup_router_options_block dnslookup_router_option_defaults = {
-  FALSE,           /* check_secondary_mx */
-  TRUE,            /* qualify_single */
-  FALSE,           /* search_parents */
-  TRUE,            /* rewrite_headers */
-  NULL,            /* widen_domains */
-  NULL,            /* mx_domains */
-  NULL,            /* mx_fail_domains */
-  NULL,            /* srv_fail_domains */
-  NULL,            /* check_srv */
-  NULL             /* fail_defer_domains */
+  .check_secondary_mx =        FALSE,
+  .qualify_single =    TRUE,
+  .search_parents =    FALSE,
+  .rewrite_headers =   TRUE,
+  .widen_domains =     NULL,
+  .mx_domains =                NULL,
+  .mx_fail_domains =   NULL,
+  .srv_fail_domains =  NULL,
+  .check_srv =         NULL,
+  .fail_defer_domains =        NULL,
+  .ipv4_only =         NULL,
+  .ipv4_prefer =       NULL,
 };
 
 
@@ -138,7 +148,7 @@ dnslookup_router_entry(
 host_item h;
 int rc;
 int widen_sep = 0;
-int whichrrs = HOST_FIND_BY_MX | HOST_FIND_BY_A;
+int whichrrs = HOST_FIND_BY_MX | HOST_FIND_BY_A | HOST_FIND_BY_AAAA;
 dnslookup_router_options_block *ob =
   (dnslookup_router_options_block *)(rblock->options_block);
 uschar *srv_service = NULL;
@@ -161,7 +171,7 @@ DEBUG(D_route)
 if (ob->check_srv)
   {
   if (  !(srv_service = expand_string(ob->check_srv))
-     && !expand_string_forcedfail)
+     && !f.expand_string_forcedfail)
     {
     addr->message = string_sprintf("%s router: failed to expand \"%s\": %s",
       rblock->name, ob->check_srv, expand_string_message);
@@ -239,6 +249,19 @@ for (;;)
     }
   else return DECLINE;
 
+  /* Check if we must request only. or prefer, ipv4 */
+
+  if (  ob->ipv4_only
+     && expand_check_condition(ob->ipv4_only, rblock->name, US"router"))
+    flags = flags & ~HOST_FIND_BY_AAAA | HOST_FIND_IPV4_ONLY;
+  else if (f.search_find_defer)
+    return DEFER;
+  if (  ob->ipv4_prefer
+     && expand_check_condition(ob->ipv4_prefer, rblock->name, US"router"))
+    flags |= HOST_FIND_IPV4_FIRST;
+  else if (f.search_find_defer)
+    return DEFER;
+
   /* Set up the rest of the initial host item. Others may get chained on if
   there is more than one IP address. We set it up here instead of outside the
   loop so as to re-initialize if a previous try succeeded but was rejected
@@ -263,9 +286,11 @@ for (;;)
     if (ob->search_parents) flags |= HOST_FIND_SEARCH_PARENTS;
     }
 
-  rc = host_find_bydns(&h, CUS rblock->ignore_target_hosts, flags, srv_service,
-    ob->srv_fail_domains, ob->mx_fail_domains,
-    &rblock->dnssec, &fully_qualified_name, &removed);
+  rc = host_find_bydns(&h, CUS rblock->ignore_target_hosts, flags,
+    srv_service, ob->srv_fail_domains, ob->mx_fail_domains,
+    &rblock->dnssec,
+    &fully_qualified_name, &removed);
+
   if (removed) setflag(addr, af_local_host_removed);
 
   /* If host found with only address records, test for the domain's being in
@@ -362,7 +387,7 @@ for (;;)
   /* If there's a syntax error, do not continue with any widening, and note
   the error. */
 
-  if (host_find_failed_syntax)
+  if (f.host_find_failed_syntax)
     {
     addr->message = string_sprintf("mail domain \"%s\" is syntactically "
       "invalid", h.name);
@@ -422,7 +447,7 @@ else if (ob->check_secondary_mx && !testflag(addr, af_local_host_removed))
 rc = rf_get_errors_address(addr, rblock, verify, &addr->prop.errors_address);
 if (rc != OK) return rc;
 
-/* Set up the additional and removeable headers for this address. */
+/* Set up the additional and removable headers for this address. */
 
 rc = rf_get_munge_headers(addr, rblock, &addr->prop.extra_headers,
   &addr->prop.remove_headers);
@@ -431,7 +456,7 @@ if (rc != OK) return rc;
 /* Get store in which to preserve the original host item, chained on
 to the address. */
 
-addr->host_list = store_get(sizeof(host_item));
+addr->host_list = store_get(sizeof(host_item), FALSE);
 addr->host_list[0] = h;
 
 /* Fill in the transport and queue the address for delivery. */
@@ -446,6 +471,7 @@ return rf_queue_add(addr, addr_local, addr_remote, rblock, pw)?
   OK : DEFER;
 }
 
+#endif   /*!MACRO_PREDEF*/
 /* End of routers/dnslookup.c */
 /* vi: aw ai sw=2
 */