X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/c988f1f4faa9f679f79beddf3c14676c5dcb8e28..0a49a7a4f1090b6f1ce1d0f9d969804c9226b53e:/src/src/routers/manualroute.c diff --git a/src/src/routers/manualroute.c b/src/src/routers/manualroute.c index 128c09df8..4130b4d17 100644 --- a/src/src/routers/manualroute.c +++ b/src/src/routers/manualroute.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/routers/manualroute.c,v 1.2 2005/01/04 10:00:44 ph10 Exp $ */ +/* $Cambridge: exim/src/src/routers/manualroute.c,v 1.7 2009/11/16 19:50:38 nm4 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2005 */ +/* Copyright (c) University of Cambridge 1995 - 2009 */ /* See the file NOTICE for conditions of use and distribution. */ @@ -16,6 +16,8 @@ /* Options specific to the manualroute router. */ optionlist manualroute_router_options[] = { + { "host_all_ignored", opt_stringptr, + (void *)(offsetof(manualroute_router_options_block, host_all_ignored)) }, { "host_find_failed", opt_stringptr, (void *)(offsetof(manualroute_router_options_block, host_find_failed)) }, { "hosts_randomize", opt_bool, @@ -37,14 +39,30 @@ int manualroute_router_options_count = /* Default private options block for the manualroute router. */ manualroute_router_options_block manualroute_router_option_defaults = { - hff_freeze, /* host_find_failed code */ + -1, /* host_all_ignored code (unset) */ + -1, /* host_find_failed code (unset) */ FALSE, /* hosts_randomize */ + US"defer", /* host_all_ignored */ US"freeze", /* host_find_failed */ NULL, /* route_data */ NULL /* route_list */ }; +/* Names and values for host_find_failed and host_all_ignored. */ + +static uschar *hff_names[] = { + US"ignore", /* MUST be first - not valid for host_all_ignored */ + US"decline", + US"defer", + US"fail", + US"freeze", + US"pass" }; + +static int hff_codes[] = { hff_ignore, hff_decline, hff_defer, hff_fail, + hff_freeze, hff_pass }; + +static int hff_count= sizeof(hff_codes)/sizeof(int); @@ -60,23 +78,34 @@ manualroute_router_init(router_instance *rblock) { manualroute_router_options_block *ob = (manualroute_router_options_block *)(rblock->options_block); +int i; /* Host_find_failed must be a recognized word */ -if (Ustrcmp(ob->host_find_failed, "freeze") == 0) - ob->hff_code = hff_freeze; -else if (Ustrcmp(ob->host_find_failed, "decline") == 0) - ob->hff_code = hff_decline; -else if (Ustrcmp(ob->host_find_failed, "defer") == 0) - ob->hff_code = hff_defer; -else if (Ustrcmp(ob->host_find_failed, "pass") == 0) - ob->hff_code = hff_pass; -else if (Ustrcmp(ob->host_find_failed, "fail") == 0) - ob->hff_code = hff_fail; -else +for (i = 0; i < hff_count; i++) + { + if (Ustrcmp(ob->host_find_failed, hff_names[i]) == 0) + { + ob->hff_code = hff_codes[i]; + break; + } + } +if (ob->hff_code < 0) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n " "unrecognized setting for host_find_failed option", rblock->name); +for (i = 1; i < hff_count; i++) /* NB starts at 1 to skip "ignore" */ + { + if (Ustrcmp(ob->host_all_ignored, hff_names[i]) == 0) + { + ob->hai_code = hff_codes[i]; + break; + } + } +if (ob->hai_code < 0) + log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n " + "unrecognized setting for host_all_ignored option", rblock->name); + /* One of route_list or route_data must be specified */ if ((ob->route_list == NULL && ob->route_data == NULL) || @@ -191,7 +220,7 @@ manualroute_router_entry( router_instance *rblock, /* data for this instantiation */ address_item *addr, /* address we are working on */ struct passwd *pw, /* passwd entry after check_local_user */ - BOOL verify, /* TRUE when verifying */ + int verify, /* v_none/v_recipient/v_sender/v_expn */ address_item **addr_local, /* add it to this if it's local */ address_item **addr_remote, /* add it to this if it's remote */ address_item **addr_new, /* put new addresses on here */ @@ -386,7 +415,7 @@ address is just accepted. */ if (hostlist[0] == 0) { - if (verify) goto ROUTED; + if (verify != v_none) goto ROUTED; addr->message = string_sprintf("error in %s router: no host(s) specified " "for domain %s", rblock->name, domain); log_write(0, LOG_MAIN, "%s", addr->message); @@ -401,11 +430,35 @@ rc = rf_lookup_hostlist(rblock, addr, rblock->ignore_target_hosts, lookup_type, ob->hff_code, addr_new); if (rc != OK) return rc; +/* If host_find_failed is set to "ignore", it is possible for all the hosts to +be ignored, in which case we will end up with an empty host list. What happens +is controlled by host_all_ignored. */ + +if (addr->host_list == NULL) + { + int i; + DEBUG(D_route) debug_printf("host_find_failed ignored every host\n"); + if (ob->hai_code == hff_decline) return DECLINE; + if (ob->hai_code == hff_pass) return PASS; + + for (i = 0; i < hff_count; i++) + if (ob->hai_code == hff_codes[i]) break; + + addr->message = string_sprintf("lookup failed for all hosts in %s router: " + "host_find_failed=ignore host_all_ignored=%s", rblock->name, hff_names[i]); + + if (ob->hai_code == hff_defer) return DEFER; + if (ob->hai_code == hff_fail) return FAIL; + + addr->special_action = SPECIAL_FREEZE; + return DEFER; + } + /* Finally, since we have done all the routing here, there must be a transport defined for these hosts. It will be a remote one, as a local transport is dealt with above. However, we don't need one if verifying only. */ -if (transport == NULL && !verify) +if (transport == NULL && verify == v_none) { log_write(0, LOG_MAIN, "Error in %s router: no transport defined", rblock->name);