X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fsrc%2Froute.c;h=09503044fb74305f7ef81177acd0baa1845a102b;hb=0f0c8159c43045f4ad847a0129dca7eddd313285;hp=324de2ab8800c0bcb91dcce5789473cec67f28ea;hpb=0a49a7a4f1090b6f1ce1d0f9d969804c9226b53e;p=exim.git diff --git a/src/src/route.c b/src/src/route.c index 324de2ab8..09503044f 100644 --- a/src/src/route.c +++ b/src/src/route.c @@ -1,10 +1,8 @@ -/* $Cambridge: exim/src/src/route.c,v 1.14 2009/11/16 19:50:37 nm4 Exp $ */ - /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2009 */ +/* Copyright (c) University of Cambridge 1995 - 2014 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions concerned with routing, and the list of generic router options. */ @@ -50,7 +48,7 @@ optionlist optionlist_routers[] = { (void *)(offsetof(router_instance, caseful_local_part)) }, { "check_local_user", opt_bool | opt_public, (void *)(offsetof(router_instance, check_local_user)) }, - { "condition", opt_stringptr|opt_public, + { "condition", opt_stringptr|opt_public|opt_rep_con, (void *)offsetof(router_instance, condition) }, { "debug_print", opt_stringptr | opt_public, (void *)offsetof(router_instance, debug_string) }, @@ -60,6 +58,8 @@ optionlist optionlist_routers[] = { (void *)offsetof(router_instance, domains) }, { "driver", opt_stringptr|opt_public, (void *)offsetof(router_instance, driver_name) }, + { "dsn_lasthop", opt_bool|opt_public, + (void *)offsetof(router_instance, dsn_lasthop) }, { "errors_to", opt_stringptr|opt_public, (void *)(offsetof(router_instance, errors_to)) }, { "expn", opt_bool|opt_public, @@ -74,9 +74,9 @@ optionlist optionlist_routers[] = { (void *)offsetof(router_instance, fallback_hosts) }, { "group", opt_expand_gid | opt_public, (void *)(offsetof(router_instance, gid)) }, - { "headers_add", opt_stringptr|opt_public, + { "headers_add", opt_stringptr|opt_public|opt_rep_str, (void *)offsetof(router_instance, extra_headers) }, - { "headers_remove", opt_stringptr|opt_public, + { "headers_remove", opt_stringptr|opt_public|opt_rep_str, (void *)offsetof(router_instance, remove_headers) }, { "ignore_target_hosts",opt_stringptr|opt_public, (void *)offsetof(router_instance, ignore_target_hosts) }, @@ -272,6 +272,13 @@ 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); + + 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); + } } } @@ -1294,67 +1301,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 * *************************************************/ @@ -1414,6 +1360,8 @@ new->p.errors_address = parent->p.errors_address; copyflag(new, addr, af_propagate); new->p.address_data = addr->p.address_data; +new->dsn_flags = addr->dsn_flags; +new->dsn_orcpt = addr->dsn_orcpt; /* As it has turned out, we haven't set headers_add or headers_remove for the @@ -1635,6 +1583,7 @@ for (r = (addr->start_router == NULL)? routers : addr->start_router; /* Set the expansion variables now that we have the affixes and the case of the local part sorted. */ + router_name = r->name; deliver_set_expansions(addr); /* For convenience, the pre-router checks are in a separate function, which @@ -1642,6 +1591,7 @@ for (r = (addr->start_router == NULL)? routers : addr->start_router; if ((rc = check_router_conditions(r, addr, verify, &pw, &error)) != OK) { + router_name = NULL; if (rc == SKIP) continue; addr->message = error; yield = rc; @@ -1672,14 +1622,15 @@ 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) { DEBUG(D_route) debug_printf("\"more\"=false: skipping remaining routers\n"); + router_name = NULL; r = NULL; break; } @@ -1718,11 +1669,22 @@ for (r = (addr->start_router == NULL)? routers : addr->start_router; /* Run the router, and handle the consequences. */ +/* ... but let us check on DSN before. If this should be the last hop for DSN + set flag +*/ + if ((r->dsn_lasthop == TRUE) && ((addr->dsn_flags & rf_dsnlasthop) == 0)) + { + addr->dsn_flags |= rf_dsnlasthop; + HDEBUG(D_route) debug_printf("DSN: last hop for %s\n", addr->address); + } + HDEBUG(D_route) debug_printf("calling %s router\n", r->name); yield = (r->info->code)(r, addr, pw, verify, paddr_local, paddr_remote, addr_new, addr_succeed); + router_name = NULL; + if (yield == FAIL) { HDEBUG(D_route) debug_printf("%s router forced address failure\n", r->name); @@ -1768,7 +1730,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) @@ -1908,8 +1871,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 */ @@ -1938,6 +1901,7 @@ DEBUG(D_route) if (h->mx >= 0) debug_printf(" MX=%d", h->mx); else if (h->mx != MX_NONE) debug_printf(" rgroup=%d", h->mx); if (h->port != PORT_NONE) debug_printf(" port=%d", h->port); + if (h->dnssec != DS_UNK) debug_printf(" dnssec=%s", h->dnssec==DS_YES ? "yes" : "no"); debug_printf("\n"); } } @@ -1952,7 +1916,27 @@ 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 || +#ifdef EXPERIMENTAL_REDIS + 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"); + } +} + deliver_set_expansions(NULL); +router_name = NULL; disable_logging = FALSE; return yield; }