Improve the consistency of logging incoming and outgoing interfaces.
[exim.git] / src / src / route.c
index 3834b836a2ca907e4324013250704c4839770de1..39aed90a3af2e254297e4070aeaa04783cab0e5f 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2014 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions concerned with routing, and the list of generic router options. */
@@ -54,14 +54,16 @@ optionlist optionlist_routers[] = {
                  (void *)offsetof(router_instance, debug_string) },
   { "disable_logging",    opt_bool | opt_public,
                  (void *)offsetof(router_instance, disable_logging) },
+  { "dnssec_request_domains",            opt_stringptr|opt_public,
+                 (void *)offsetof(router_instance, dnssec.request) },
+  { "dnssec_require_domains",            opt_stringptr|opt_public,
+                 (void *)offsetof(router_instance, dnssec.require) },
   { "domains",            opt_stringptr|opt_public,
                  (void *)offsetof(router_instance, domains) },
   { "driver",             opt_stringptr|opt_public,
                  (void *)offsetof(router_instance, driver_name) },
-  #ifdef EXPERIMENTAL_DSN
   { "dsn_lasthop",        opt_bool|opt_public,
                  (void *)offsetof(router_instance, dsn_lasthop) },
-  #endif
   { "errors_to",          opt_stringptr|opt_public,
                  (void *)(offsetof(router_instance, errors_to)) },
   { "expn",               opt_bool|opt_public,
@@ -275,14 +277,12 @@ for (r = routers; r != NULL; r = r->next)
   if (r->pass_router_name != NULL)
     set_router(r, r->pass_router_name, &(r->pass_router), TRUE);
 
-  #ifdef EXPERIMENTAL_DSN
-    DEBUG(D_route) {
+  DEBUG(D_route) {
       if (r->dsn_lasthop == FALSE)
         debug_printf("DSN: %s propagating DSN\n", r->name);
       else
         debug_printf("DSN: %s lasthop set\n", r->name);
       }
-  #endif
   }
 }
 
@@ -323,11 +323,11 @@ Returns:        length of matching prefix or zero
 */
 
 int
-route_check_prefix(uschar *local_part, uschar *prefixes)
+route_check_prefix(const uschar *local_part, const uschar *prefixes)
 {
 int sep = 0;
 uschar *prefix;
-uschar *listptr = prefixes;
+const uschar *listptr = prefixes;
 uschar prebuf[64];
 
 while ((prefix = string_nextinlist(&listptr, &sep, prebuf, sizeof(prebuf)))
@@ -336,7 +336,7 @@ while ((prefix = string_nextinlist(&listptr, &sep, prebuf, sizeof(prebuf)))
   int plen = Ustrlen(prefix);
   if (prefix[0] == '*')
     {
-    uschar *p;
+    const uschar *p;
     prefix++;
     for (p = local_part + Ustrlen(local_part) - (--plen);
          p >= local_part; p--)
@@ -367,12 +367,12 @@ Returns:        length of matching suffix or zero
 */
 
 int
-route_check_suffix(uschar *local_part, uschar *suffixes)
+route_check_suffix(const uschar *local_part, const uschar *suffixes)
 {
 int sep = 0;
 int alen = Ustrlen(local_part);
 uschar *suffix;
-uschar *listptr = suffixes;
+const uschar *listptr = suffixes;
 uschar sufbuf[64];
 
 while ((suffix = string_nextinlist(&listptr, &sep, sufbuf, sizeof(sufbuf)))
@@ -381,7 +381,7 @@ while ((suffix = string_nextinlist(&listptr, &sep, sufbuf, sizeof(sufbuf)))
   int slen = Ustrlen(suffix);
   if (suffix[slen-1] == '*')
     {
-    uschar *p, *pend;
+    const uschar *p, *pend;
     pend = local_part + alen - (--slen) + 1;
     for (p = local_part; p < pend; p++)
       if (strncmpic(suffix, p, slen) == 0) return alen - (p - local_part);
@@ -424,9 +424,9 @@ Returns:         OK     item is in list
 */
 
 static int
-route_check_dls(uschar *rname, uschar *type, uschar *list, tree_node
-  **anchorptr, unsigned int *cache_bits, int listtype, uschar *domloc,
-  uschar **ldata, BOOL caseless, uschar **perror)
+route_check_dls(uschar *rname, uschar *type, const uschar *list,
+  tree_node **anchorptr, unsigned int *cache_bits, int listtype,
+  const uschar *domloc, const uschar **ldata, BOOL caseless, uschar **perror)
 {
 int rc;
 
@@ -446,7 +446,7 @@ else
   {
   uschar *address = (sender_address == NULL)? US"" : sender_address;
   rc = match_address_list(address, TRUE, TRUE, &list, cache_bits, -1, 0,
-    &sender_data);
+    CUSS &sender_data);
   }
 
 switch(rc)
@@ -574,14 +574,15 @@ Returns:   OK if s == NULL or all tests are as required
            SKIP otherwise
 */
 
-int
-check_files(uschar *s, uschar **perror)
+static int
+check_files(const uschar *s, uschar **perror)
 {
 int sep = 0;              /* List has default separators */
 uid_t uid = 0;            /* For picky compilers */
 gid_t gid = 0;            /* For picky compilers */
 BOOL ugid_set = FALSE;
-uschar *check, *listptr;
+const uschar *listptr;
+uschar *check;
 uschar buffer[1024];
 
 if (s == NULL) return OK;
@@ -589,8 +590,7 @@ if (s == NULL) return OK;
 DEBUG(D_route) debug_printf("checking require_files\n");
 
 listptr = s;
-while ((check = string_nextinlist(&listptr, &sep, buffer, sizeof(buffer)))
-        != NULL)
+while ((check = string_nextinlist(&listptr, &sep, buffer, sizeof(buffer))))
   {
   int rc;
   int eacces_code = 0;
@@ -889,8 +889,8 @@ if (verify == v_expn && !r->expn)
 /* Skip this router if there's a domain mismatch. */
 
 if ((rc = route_check_dls(r->name, US"domains", r->domains, &domainlist_anchor,
-     addr->domain_cache, TRUE, addr->domain, &deliver_domain_data, MCL_DOMAIN,
-     perror)) != OK)
+     addr->domain_cache, TRUE, addr->domain, CUSS &deliver_domain_data,
+     MCL_DOMAIN, perror)) != OK)
   return rc;
 
 /* Skip this router if there's a local part mismatch. We want to pass over the
@@ -917,8 +917,8 @@ else
 
 if ((rc = route_check_dls(r->name, US"local_parts", r->local_parts,
        &localpartlist_anchor, localpart_cache, MCL_LOCALPART,
-       check_local_part, &deliver_localpart_data, !r->caseful_local_part,
-       perror)) != OK)
+       check_local_part, CUSS &deliver_localpart_data,
+       !r->caseful_local_part, perror)) != OK)
   return rc;
 
 /* If the check_local_user option is set, check that the local_part is the
@@ -1092,7 +1092,7 @@ static uschar lastgecos[128];
 static uschar lastshell[128];
 
 BOOL
-route_finduser(uschar *s, struct passwd **pw, uid_t *return_uid)
+route_finduser(const uschar *s, struct passwd **pw, uid_t *return_uid)
 {
 BOOL cache_set = (Ustrcmp(lastname, s) == 0);
 
@@ -1305,67 +1305,6 @@ return yield;
 
 
 
-/*************************************************
-*           Sort out "more" or "unseen"          *
-*************************************************/
-
-/* These values are usually fixed boolean values, but they are permitted to be
-expanded strings.
-
-Arguments:
-  addr       address being routed
-  rname      the router name
-  oname      the option name
-  bvalue     the router's boolean value
-  svalue     the router's string value
-  rvalue     where to put the returned value
-
-Returns:     OK     value placed in rvalue
-             DEFER  expansion failed
-*/
-
-static int
-exp_bool(address_item *addr, uschar *rname, uschar *oname, BOOL bvalue,
-  uschar *svalue, BOOL *rvalue)
-{
-uschar *expanded;
-if (svalue == NULL) { *rvalue = bvalue; return OK; }
-
-expanded = expand_string(svalue);
-if (expanded == NULL)
-  {
-  if (expand_string_forcedfail)
-    {
-    DEBUG(D_route) debug_printf("expansion of \"%s\" forced failure\n", oname);
-    *rvalue = bvalue;
-    return OK;
-    }
-  addr->message = string_sprintf("failed to expand \"%s\" in %s router: %s",
-      oname, rname, expand_string_message);
-  DEBUG(D_route) debug_printf("%s\n", addr->message);
-  return DEFER;
-  }
-
-DEBUG(D_route) debug_printf("expansion of \"%s\" yields \"%s\"\n", oname,
-  expanded);
-
-if (strcmpic(expanded, US"true") == 0 || strcmpic(expanded, US"yes") == 0)
-  *rvalue = TRUE;
-else if (strcmpic(expanded, US"false") == 0 || strcmpic(expanded, US"no") == 0)
-  *rvalue = FALSE;
-else
-  {
-  addr->message = string_sprintf("\"%s\" is not a valid value for the "
-    "\"%s\" option in the %s router", expanded, oname, rname);
-  return DEFER;
-  }
-
-return OK;
-}
-
-
-
-
 /*************************************************
 *            Handle an unseen routing            *
 *************************************************/
@@ -1407,8 +1346,8 @@ from the original address' parent, if present, otherwise unset. */
 
 *parent = *addr;
 parent->child_count = 2;
-parent->p.errors_address =
-  (addr->parent == NULL)? NULL : addr->parent->p.errors_address;
+parent->prop.errors_address =
+  (addr->parent == NULL)? NULL : addr->parent->prop.errors_address;
 
 /* The routed address gets a new parent. */
 
@@ -1419,16 +1358,14 @@ was set from the original parent (or to NULL) - see above. We do NOT want to
 take the errors address from the unseen router. */
 
 new->parent = parent;
-new->p.errors_address = parent->p.errors_address;
+new->prop.errors_address = parent->prop.errors_address;
 
 /* Copy the propagated flags and address_data from the original. */
 
 copyflag(new, addr, af_propagate);
-new->p.address_data = addr->p.address_data;
-#ifdef EXPERIMENTAL_DSN
+new->prop.address_data = addr->prop.address_data;
 new->dsn_flags = addr->dsn_flags;
 new->dsn_orcpt = addr->dsn_orcpt;
-#endif
 
 
 /* As it has turned out, we haven't set headers_add or headers_remove for the
@@ -1504,7 +1441,7 @@ route_address(address_item *addr, address_item **paddr_local,
 int yield = OK;
 BOOL unseen;
 router_instance *r, *nextr;
-uschar *old_domain = addr->domain;
+const uschar *old_domain = addr->domain;
 
 HDEBUG(D_route)
   {
@@ -1689,8 +1626,8 @@ for (r = (addr->start_router == NULL)? routers : addr->start_router;
 
         /* Expand "more" if necessary; DEFER => an expansion failed */
 
-        yield = exp_bool(addr, r->name, US"more", r->more, r->expand_more,
-          &more);
+        yield = exp_bool(addr, US"router", r->name, D_route,
+                       US"more", r->more, r->expand_more, &more);
         if (yield != OK) goto ROUTE_EXIT;
 
         if (!more)
@@ -1712,7 +1649,7 @@ for (r = (addr->start_router == NULL)? routers : addr->start_router;
         goto ROUTE_EXIT;
         }
       }
-    addr->p.address_data = deliver_address_data;
+    addr->prop.address_data = deliver_address_data;
     }
 
   /* We are finally cleared for take-off with this router. Clear the the flag
@@ -1736,7 +1673,6 @@ for (r = (addr->start_router == NULL)? routers : addr->start_router;
 
   /* Run the router, and handle the consequences. */
 
-#ifdef EXPERIMENTAL_DSN
 /* ... but let us check on DSN before. If this should be the last hop for DSN
    set flag
 */
@@ -1745,7 +1681,6 @@ for (r = (addr->start_router == NULL)? routers : addr->start_router;
     addr->dsn_flags |= rf_dsnlasthop;
     HDEBUG(D_route) debug_printf("DSN: last hop for %s\n", addr->address);
   }
-#endif
 
   HDEBUG(D_route) debug_printf("calling %s router\n", r->name);
 
@@ -1799,7 +1734,8 @@ for (r = (addr->start_router == NULL)? routers : addr->start_router;
     {
     /* Expand "more" if necessary */
 
-    yield = exp_bool(addr, r->name, US"more", r->more, r->expand_more, &more);
+    yield = exp_bool(addr, US"router", r->name, D_route,
+                       US"more", r->more, r->expand_more, &more);
     if (yield != OK) goto ROUTE_EXIT;
 
     if (!more)
@@ -1939,8 +1875,8 @@ if (r->translate_ip_address != NULL)
 /* See if this is an unseen routing; first expand the option if necessary.
 DEFER can be given if the expansion fails */
 
-yield = exp_bool(addr, r->name, US"unseen", r->unseen, r->expand_unseen,
-  &unseen);
+yield = exp_bool(addr, US"router", r->name, D_route,
+               US"unseen", r->unseen, r->expand_unseen, &unseen);
 if (yield != OK) goto ROUTE_EXIT;
 
 /* Debugging output recording a successful routing */
@@ -1959,8 +1895,8 @@ DEBUG(D_route)
   debug_printf("  transport: %s\n", (addr->transport == NULL)?
     US"<none>" : addr->transport->name);
 
-  if (addr->p.errors_address != NULL)
-    debug_printf("  errors to %s\n", addr->p.errors_address);
+  if (addr->prop.errors_address != NULL)
+    debug_printf("  errors to %s\n", addr->prop.errors_address);
 
   for (h = addr->host_list; h != NULL; h = h->next)
     {
@@ -1984,24 +1920,23 @@ if (unseen && r->next != NULL)
 /* Unset the address expansions, and return the final result. */
 
 ROUTE_EXIT:
-if (yield == DEFER) {
-  if (
-    ((Ustrstr(addr->message, "failed to expand") != NULL) || (Ustrstr(addr->message, "expansion of ") != NULL)) &&
-    (
-      Ustrstr(addr->message, "mysql") != NULL ||
-      Ustrstr(addr->message, "pgsql") != NULL ||
+if (  yield == DEFER
+   && addr->message
+   && (  Ustrstr(addr->message, "failed to expand") != NULL
+      || Ustrstr(addr->message, "expansion of ") != NULL
+      )
+   && (  Ustrstr(addr->message, "mysql") != NULL
+      || Ustrstr(addr->message, "pgsql") != NULL
 #ifdef EXPERIMENTAL_REDIS
-      Ustrstr(addr->message, "redis") != NULL ||
+      || Ustrstr(addr->message, "redis") != NULL
 #endif
-      Ustrstr(addr->message, "sqlite") != NULL ||
-      Ustrstr(addr->message, "ldap:") != NULL ||
-      Ustrstr(addr->message, "ldapdn:") != NULL ||
-      Ustrstr(addr->message, "ldapm:") != NULL
-    )
-  ) {
-    addr->message = string_sprintf("Temporary internal error");
-  }
-}
+      || Ustrstr(addr->message, "sqlite") != NULL
+      || Ustrstr(addr->message, "ldap:") != NULL
+      || Ustrstr(addr->message, "ldapdn:") != NULL
+      || Ustrstr(addr->message, "ldapm:") != NULL
+      )
+   )
+  addr->message = string_sprintf("Temporary internal error");
 
 deliver_set_expansions(NULL);
 router_name = NULL;