const uschar * save_local = deliver_localpart;
const uschar * save_host = deliver_host;
const uschar * save_address = deliver_host_address;
-uschar * save_rn = router_name, * save_tn = transport_name;
+const uschar * save_rn = router_name;
+uschar * save_tn = transport_name;
const int save_port = deliver_host_port;
-router_name = addr->router ? addr->router->name : NULL;
+router_name = addr->router ? addr->router->drinst.name : NULL;
deliver_domain = addr->domain;
deliver_localpart = addr->local_part;
deliver_host = addr->host_used ? addr->host_used->name : NULL;
/* For a delivery from a system filter, there may not be a router */
if (addr->router)
- g = string_append(g, 2, US" R=", addr->router->name);
+ g = string_append(g, 2, US" R=", addr->router->drinst.name);
g = string_append(g, 2, US" T=", addr->transport->name);
if (driver_name)
{
if (driver_kind[1] == 't' && addr->router)
- g = string_append(g, 2, US" R=", addr->router->name);
+ g = string_append(g, 2, US" R=", addr->router->drinst.name);
g = string_fmt_append(g, " %c=%s", toupper(driver_kind[1]), driver_name);
}
else if (driver_kind)
g = string_append(g, 3, US" P=<", used_return_path, US">");
if (addr->router)
- g = string_append(g, 2, US" R=", addr->router->name);
+ g = string_append(g, 2, US" R=", addr->router->drinst.name);
if (addr->transport)
g = string_append(g, 2, US" T=", addr->transport->name);
{
if (addr->router)
{
- driver_name = addr->router->name;
+ driver_name = addr->router->drinst.name;
driver_kind = US" router";
f.disable_logging = addr->router->disable_logging;
}
/* Setting these globals in the subprocess means we need never clear them */
transport_name = tp->name;
- if (addr->router) router_name = addr->router->name;
+ if (addr->router) router_name = addr->router->drinst.name;
driver_srcfile = tp->srcfile;
driver_srcline = tp->srcline;
logflags |= LOG_PANIC;
f.disable_logging = FALSE; /* Jic */
addr->message = addr->router
- ? string_sprintf("No transport set by %s router", addr->router->name)
+ ? string_sprintf("No transport set by %s router", addr->router->drinst.name)
: US"No transport set by system filter";
post_process_one(addr, DEFER, logflags, EXIM_DTYPE_TRANSPORT, 0);
continue;
/* Setting these globals in the subprocess means we need never clear them */
transport_name = tp->name;
- if (addr->router) router_name = addr->router->name;
+ if (addr->router) router_name = addr->router->drinst.name;
driver_srcfile = tp->srcfile;
driver_srcline = tp->srcline;
"DSN: envid: %s ret: %d\n"
"DSN: Final recipient: %s\n"
"DSN: Remote SMTP server supports DSN: %d\n",
- a->router ? a->router->name : US"(unknown)",
+ a->router ? a->router->drinst.name : US"(unknown)",
a->address,
sender_address,
a->dsn_orcpt ? a->dsn_orcpt : US"NULL",
#include "routers/rf_functions.h"
#ifdef ROUTER_ACCEPT
-#include "routers/accept.h"
+# include "routers/accept.h"
#endif
#ifdef ROUTER_DNSLOOKUP
-#include "routers/dnslookup.h"
+# include "routers/dnslookup.h"
#endif
#ifdef ROUTER_MANUALROUTE
-#include "routers/manualroute.h"
+# include "routers/manualroute.h"
#endif
#ifdef ROUTER_IPLITERAL
-#include "routers/ipliteral.h"
+# include "routers/ipliteral.h"
#endif
#ifdef ROUTER_IPLOOKUP
-#include "routers/iplookup.h"
+# include "routers/iplookup.h"
#endif
#ifdef ROUTER_QUERYPROGRAM
-#include "routers/queryprogram.h"
+# include "routers/queryprogram.h"
#endif
#ifdef ROUTER_REDIRECT
-#include "routers/redirect.h"
+# include "routers/redirect.h"
#endif
#ifdef TRANSPORT_APPENDFILE
-#include "transports/appendfile.h"
+# include "transports/appendfile.h"
#endif
#ifdef TRANSPORT_AUTOREPLY
-#include "transports/autoreply.h"
+# include "transports/autoreply.h"
#endif
#ifdef TRANSPORT_LMTP
-#include "transports/lmtp.h"
+# include "transports/lmtp.h"
#endif
#ifdef TRANSPORT_PIPE
-#include "transports/pipe.h"
+# include "transports/pipe.h"
#endif
#ifdef EXPERIMENTAL_QUEUEFILE
-#include "transports/queuefile.h"
+# include "transports/queuefile.h"
#endif
#ifdef TRANSPORT_SMTP
-#include "transports/smtp.h"
+# include "transports/smtp.h"
#endif
router_info routers_available[] = {
#ifdef ROUTER_ACCEPT
{
- .driver_name = US"accept",
- .options = accept_router_options,
- .options_count = &accept_router_options_count,
- .options_block = &accept_router_option_defaults,
- .options_len = sizeof(accept_router_options_block),
- .init = accept_router_init,
+ .drinfo = {
+ .driver_name = US"accept",
+ .options = accept_router_options,
+ .options_count = &accept_router_options_count,
+ .options_block = &accept_router_option_defaults,
+ .options_len = sizeof(accept_router_options_block),
+ .init = accept_router_init,
+ },
.code = accept_router_entry,
.tidyup = NULL, /* no tidyup entry */
.ri_flags = ri_yestransport
#endif
#ifdef ROUTER_DNSLOOKUP
{
- .driver_name = US"dnslookup",
- .options = dnslookup_router_options,
- .options_count = &dnslookup_router_options_count,
- .options_block = &dnslookup_router_option_defaults,
- .options_len = sizeof(dnslookup_router_options_block),
- .init = dnslookup_router_init,
+ .drinfo = {
+ .driver_name = US"dnslookup",
+ .options = dnslookup_router_options,
+ .options_count = &dnslookup_router_options_count,
+ .options_block = &dnslookup_router_option_defaults,
+ .options_len = sizeof(dnslookup_router_options_block),
+ .init = dnslookup_router_init,
+ },
.code = dnslookup_router_entry,
.tidyup = NULL, /* no tidyup entry */
.ri_flags = ri_yestransport
#endif
#ifdef ROUTER_IPLITERAL
{
- .driver_name = US"ipliteral",
- .options = ipliteral_router_options,
- .options_count = &ipliteral_router_options_count,
- .options_block = &ipliteral_router_option_defaults,
- .options_len = sizeof(ipliteral_router_options_block),
- .init = ipliteral_router_init,
+ .drinfo = {
+ .driver_name = US"ipliteral",
+ .options = ipliteral_router_options,
+ .options_count = &ipliteral_router_options_count,
+ .options_block = &ipliteral_router_option_defaults,
+ .options_len = sizeof(ipliteral_router_options_block),
+ .init = ipliteral_router_init,
+ },
.code = ipliteral_router_entry,
.tidyup = NULL, /* no tidyup entry */
.ri_flags = ri_yestransport
#endif
#ifdef ROUTER_IPLOOKUP
{
- .driver_name = US"iplookup",
- .options = iplookup_router_options,
- .options_count = &iplookup_router_options_count,
- .options_block = &iplookup_router_option_defaults,
- .options_len = sizeof(iplookup_router_options_block),
- .init = iplookup_router_init,
+ .drinfo = {
+ .driver_name = US"iplookup",
+ .options = iplookup_router_options,
+ .options_count = &iplookup_router_options_count,
+ .options_block = &iplookup_router_option_defaults,
+ .options_len = sizeof(iplookup_router_options_block),
+ .init = iplookup_router_init,
+ },
.code = iplookup_router_entry,
.tidyup = NULL, /* no tidyup entry */
.ri_flags = ri_notransport
#endif
#ifdef ROUTER_MANUALROUTE
{
- .driver_name = US"manualroute",
- .options = manualroute_router_options,
- .options_count = &manualroute_router_options_count,
- .options_block = &manualroute_router_option_defaults,
- .options_len = sizeof(manualroute_router_options_block),
- .init = manualroute_router_init,
+ .drinfo = {
+ .driver_name = US"manualroute",
+ .options = manualroute_router_options,
+ .options_count = &manualroute_router_options_count,
+ .options_block = &manualroute_router_option_defaults,
+ .options_len = sizeof(manualroute_router_options_block),
+ .init = manualroute_router_init,
+ },
.code = manualroute_router_entry,
.tidyup = NULL, /* no tidyup entry */
.ri_flags = 0
#endif
#ifdef ROUTER_QUERYPROGRAM
{
- .driver_name = US"queryprogram",
- .options = queryprogram_router_options,
- .options_count = &queryprogram_router_options_count,
- .options_block = &queryprogram_router_option_defaults,
- .options_len = sizeof(queryprogram_router_options_block),
- .init = queryprogram_router_init,
+ .drinfo = {
+ .driver_name = US"queryprogram",
+ .options = queryprogram_router_options,
+ .options_count = &queryprogram_router_options_count,
+ .options_block = &queryprogram_router_option_defaults,
+ .options_len = sizeof(queryprogram_router_options_block),
+ .init = queryprogram_router_init,
+ },
.code = queryprogram_router_entry,
.tidyup = NULL, /* no tidyup entry */
.ri_flags = 0
#endif
#ifdef ROUTER_REDIRECT
{
- .driver_name = US"redirect",
- .options = redirect_router_options,
- .options_count = &redirect_router_options_count,
- .options_block = &redirect_router_option_defaults,
- .options_len = sizeof(redirect_router_options_block),
- .init = redirect_router_init,
+ .drinfo = {
+ .driver_name = US"redirect",
+ .options = redirect_router_options,
+ .options_count = &redirect_router_options_count,
+ .options_block = &redirect_router_option_defaults,
+ .options_len = sizeof(redirect_router_options_block),
+ .init = redirect_router_init,
+ },
.code = redirect_router_entry,
.tidyup = NULL, /* no tidyup entry */
.ri_flags = ri_notransport
route_show_supported(gstring * g)
{
g = string_cat(g, US"Routers:");
-for (router_info * rr = routers_available; rr->driver_name[0]; rr++)
- g = string_fmt_append(g, " %s", rr->driver_name);
+for (router_info * rr = routers_available; rr->drinfo.driver_name[0]; rr++)
+ g = string_fmt_append(g, " %s", rr->drinfo.driver_name);
return string_cat(g, US"\n");
}
/* These need to be at file level for old versions of gcc (2.95.2 reported),
- * which give parse errors on an extern in function scope. Each entry needs
- * to also be invoked in init_lookup_list() below */
+which give parse errors on an extern in function scope. Each entry needs
+to also be invoked in init_lookup_list() below */
#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
extern lookup_module_info cdb_lookup_module_info;
*/
BOOL
-expand_check_condition(uschar *condition, uschar *m1, uschar *m2)
+expand_check_condition(const uschar * condition,
+ const uschar * m1, const uschar * m2)
{
-uschar * ss = expand_string(condition);
+const uschar * ss = expand_cstring(condition);
if (!ss)
{
if (!f.expand_string_forcedfail && !f.search_find_defer)
int
exp_bool(address_item * addr,
- uschar * mtype, uschar * mname, unsigned dbg_opt,
+ const uschar * mtype, const uschar * mname, unsigned dbg_opt,
uschar * oname, BOOL bvalue,
- uschar * svalue, BOOL * rvalue)
+ const uschar * svalue, BOOL * rvalue)
{
-uschar * expanded;
+const uschar * expanded;
DEBUG(D_expand) debug_printf("try option %s\n", oname);
if (!svalue) { *rvalue = bvalue; return OK; }
-if (!(expanded = expand_string(svalue)))
+if (!(expanded = expand_cstring(svalue)))
{
if (f.expand_string_forcedfail)
{
extern void exim_setugid(uid_t, gid_t, BOOL, const uschar *);
extern void exim_underbar_exit(int) NORETURN;
extern void exim_wait_tick(struct timeval *, int);
-extern int exp_bool(address_item *addr,
- uschar *mtype, uschar *mname, unsigned dgb_opt, uschar *oname, BOOL bvalue,
- uschar *svalue, BOOL *rvalue);
-extern BOOL expand_check_condition(uschar *, uschar *, uschar *);
+extern int exp_bool(address_item *,
+ const uschar *, const uschar *, unsigned, uschar *, BOOL bvalue,
+ const uschar *, BOOL *);
+extern BOOL expand_check_condition(const uschar *, const uschar *, const uschar *);
extern uschar *expand_file_big_buffer(const uschar *);
extern uschar *expand_string(uschar *); /* public, cannot make const */
extern const uschar *expand_string_2(const uschar *, BOOL *);
uid_t root_uid = ROOT_UID;
router_instance *routers = NULL;
-router_instance router_defaults = {
- .next = NULL,
- .name = NULL,
- .info = NULL,
- .options_block = NULL,
- .driver_name = NULL,
- .address_data = NULL,
-#ifdef EXPERIMENTAL_BRIGHTMAIL
- .bmi_rule = NULL,
-#endif
- .cannot_route_message = NULL,
- .condition = NULL,
- .current_directory = NULL,
- .debug_string = NULL,
- .domains = NULL,
- .errors_to = NULL,
- .expand_gid = NULL,
- .expand_uid = NULL,
- .expand_more = NULL,
- .expand_unseen = NULL,
- .extra_headers = NULL,
- .fallback_hosts = NULL,
- .home_directory = NULL,
- .ignore_target_hosts = NULL,
- .local_parts = NULL,
- .pass_router_name = NULL,
- .prefix = NULL,
- .redirect_router_name = NULL,
- .remove_headers = NULL,
- .require_files = NULL,
- .router_home_directory = NULL,
+/* All elements not mentioned will be 0/NULL/FALSE */
+router_instance router_defaults = {
.self = US"freeze",
- .senders = NULL,
- .suffix = NULL,
- .translate_ip_address = NULL,
- .transport_name = NULL,
.address_test = TRUE,
-#ifdef EXPERIMENTAL_BRIGHTMAIL
- .bmi_deliver_alternate = FALSE,
- .bmi_deliver_default = FALSE,
- .bmi_dont_deliver = FALSE,
-#endif
.expn = TRUE,
- .caseful_local_part = FALSE,
- .check_local_user = FALSE,
- .disable_logging = FALSE,
- .fail_verify_recipient = FALSE,
- .fail_verify_sender = FALSE,
- .gid_set = FALSE,
- .initgroups = FALSE,
.log_as_local = TRUE_UNSET,
.more = TRUE,
- .pass_on_timeout = FALSE,
- .prefix_optional = FALSE,
.repeat_use = TRUE,
.retry_use_local_part = TRUE_UNSET,
- .same_domain_copy_routing = FALSE,
- .self_rewrite = FALSE,
- .set = NULL,
- .suffix_optional = FALSE,
- .verify_only = FALSE,
.verify_recipient = TRUE,
.verify_sender = TRUE,
- .uid_set = FALSE,
- .unseen = FALSE,
- .dsn_lasthop = FALSE,
.self_code = self_freeze,
.uid = (uid_t)(-1),
.gid = (gid_t)(-1),
- .fallback_hostlist = NULL,
- .transport = NULL,
- .pass_router = NULL,
- .redirect_router = NULL,
-
.dnssec = { .request= US"*", .require=NULL },
};
-uschar *router_name = NULL;
+const uschar *router_name = NULL;
tree_node *router_var = NULL;
ip_address_item *running_interfaces = NULL;
extern router_info routers_available[];/* Vector of available routers */
extern router_instance *routers; /* Chain of instantiated routers */
extern router_instance router_defaults;/* Default values */
-extern uschar *router_name; /* Name of router last started */
+extern const uschar *router_name; /* Name of router last started */
extern tree_node *router_var; /* Variables set by router */
extern ip_address_item *running_interfaces; /* Host's running interfaces */
extern uschar *running_status; /* Flag string for testing */
if (listptr == o->v.value)
return US o->name;
-for (router_instance * r = routers; r; r = r->next)
- if (router_name && Ustrcmp(r->name, router_name) == 0)
- {
- const router_info * ri = r->info;
-
- /* Check for a listptr match first */
-
- for (optionlist * o = optionlist_routers; /* generic options */
- o < optionlist_routers + optionlist_routers_size; o++)
- if ( (o->type & opt_mask) == opt_stringptr
- && listptr == CS r + o->v.offset)
- return US o->name;
-
- for (optionlist * o = ri->options; /* private options */
- o < ri->options + *ri->options_count; o++)
- if ( (o->type & opt_mask) == opt_stringptr
- && listptr == CS (r->options_block) + o->v.offset)
- return US o->name;
-
- /* Check for a list addr match, unless null */
-
- if (!list) continue;
-
- for (optionlist * o = optionlist_routers; /* generic options */
- o < optionlist_routers + optionlist_routers_size; o++)
- if ( (o->type & opt_mask) == opt_stringptr
- && list == * USS(CS r + o->v.offset))
- if (name) return string_sprintf("DUP: %s %s vs. %s %s",
- drname, name, r->name, o->name);
- else { name = US o->name; drname = r->name; }
-
- for (optionlist * o = ri->options; /* private options */
- o < ri->options + *ri->options_count; o++)
- if ( (o->type & opt_mask) == opt_stringptr
- && list == * USS(CS (r->options_block) + o->v.offset))
- if (name) return string_sprintf("DUP: %s %s vs. %s %s",
- drname, name, r->name, o->name);
- else { name = US o->name; drname = r->name; }
- }
+if (router_name)
+ for (const driver_instance * rd = (driver_instance *)routers;
+ rd; rd = rd->next) if (Ustrcmp(rd->name, router_name) == 0)
+ {
+ const router_instance * r = (router_instance *)rd;
+ const router_info * ri = (router_info *)rd->info;
+
+ /* Check for a listptr match first */
+
+ for (optionlist * o = optionlist_routers; /* generic options */
+ o < optionlist_routers + optionlist_routers_size; o++)
+ if ( (o->type & opt_mask) == opt_stringptr
+ && listptr == CS r + o->v.offset)
+ return US o->name;
+
+ for (optionlist * o = ri->drinfo.options; /* private options */
+ o < ri->drinfo.options + *ri->drinfo.options_count; o++)
+ if ( (o->type & opt_mask) == opt_stringptr
+ && listptr == CS rd->options_block + o->v.offset)
+ return US o->name;
+
+ /* Check for a list addr match, unless null */
+
+ if (!list) continue;
+
+ for (optionlist * o = optionlist_routers; /* generic options */
+ o < optionlist_routers + optionlist_routers_size; o++)
+ if ( (o->type & opt_mask) == opt_stringptr
+ && list == * USS(CS r + o->v.offset))
+ if (name)
+ return string_sprintf("DUP: %s %s vs. %s %s",
+ drname, name, rd->name, o->name);
+ else
+ { name = US o->name; drname = rd->name; }
+
+ for (optionlist * o = ri->drinfo.options; /* private options */
+ o < ri->drinfo.options + *ri->drinfo.options_count; o++)
+ if ( (o->type & opt_mask) == opt_stringptr
+ && list == * USS(CS rd->options_block + o->v.offset))
+ if (name)
+ return string_sprintf("DUP: %s %s vs. %s %s",
+ drname, name, rd->name, o->name);
+ else
+ { name = US o->name; drname = rd->name; }
+ }
-for (transport_instance * t = transports; t; t = t->next)
- if (transport_name && Ustrcmp(t->name, transport_name) == 0)
- {
- const transport_info * ti = t->info;
-
- /* Check for a listptr match first */
-
- for (optionlist * o = optionlist_transports; /* generic options */
- o < optionlist_transports + optionlist_transports_size; o++)
- if ( (o->type & opt_mask) == opt_stringptr
- && listptr == CS t + o->v.offset)
- return US o->name;
-
- for (optionlist * o = ti->options; /* private options */
- o < ti->options + *ti->options_count; o++)
- if ( (o->type & opt_mask) == opt_stringptr
- && listptr == CS t->options_block + o->v.offset)
- return US o->name;
-
- /* Check for a list addr match, unless null */
-
- if (!list) continue;
-
- for (optionlist * o = optionlist_transports; /* generic options */
- o < optionlist_transports + optionlist_transports_size; o++)
- if ( (o->type & opt_mask) == opt_stringptr
- && list == * USS(CS t + o->v.offset))
- if (name) return string_sprintf("DUP: %s %s vs. %s %s",
- drname, name, t->name, o->name);
- else { name = US o->name; drname = t->name; }
-
- for (optionlist * o = ti->options; /* private options */
- o < ti->options + *ti->options_count; o++)
- if ( (o->type & opt_mask) == opt_stringptr
- && list == * USS(CS t->options_block + o->v.offset))
- if (name) return string_sprintf("DUP: %s %s vs. %s %s",
- drname, name, t->name, o->name);
- else { name = US o->name; drname = t->name; }
- }
+if (transport_name)
+ for (transport_instance * t = transports; t; t = t->next)
+ if (Ustrcmp(t->name, transport_name) == 0)
+ {
+ const transport_info * ti = t->info;
+
+ /* Check for a listptr match first */
+
+ for (optionlist * o = optionlist_transports; /* generic options */
+ o < optionlist_transports + optionlist_transports_size; o++)
+ if ( (o->type & opt_mask) == opt_stringptr
+ && listptr == CS t + o->v.offset)
+ return US o->name;
+
+ for (optionlist * o = ti->options; /* private options */
+ o < ti->options + *ti->options_count; o++)
+ if ( (o->type & opt_mask) == opt_stringptr
+ && listptr == CS t->options_block + o->v.offset)
+ return US o->name;
+
+ /* Check for a list addr match, unless null */
+
+ if (!list) continue;
+
+ for (optionlist * o = optionlist_transports; /* generic options */
+ o < optionlist_transports + optionlist_transports_size; o++)
+ if ( (o->type & opt_mask) == opt_stringptr
+ && list == * USS(CS t + o->v.offset))
+ if (name) return string_sprintf("DUP: %s %s vs. %s %s",
+ drname, name, t->name, o->name);
+ else { name = US o->name; drname = t->name; }
+
+ for (optionlist * o = ti->options; /* private options */
+ o < ti->options + *ti->options_count; o++)
+ if ( (o->type & opt_mask) == opt_stringptr
+ && list == * USS(CS t->options_block + o->v.offset))
+ if (name) return string_sprintf("DUP: %s %s vs. %s %s",
+ drname, name, t->name, o->name);
+ else { name = US o->name; drname = t->name; }
+ }
return name ? name : US"";
}
for (; d; d = d->next)
{
BOOL rc = FALSE;
+ driver_info * di = d->info;
+
if (!name)
printf("\n%s %s:\n", d->name, type);
else if (Ustrcmp(d->name, name) != 0) continue;
if (!(ol->type & opt_hidden))
rc |= print_ol(ol, US ol->name, d, ol2, size, no_labels);
- for (optionlist * ol = d->info->options;
- ol < d->info->options + *(d->info->options_count); ol++)
+ for (optionlist * ol = di->options;
+ ol < di->options + *di->options_count; ol++)
if (!(ol->type & opt_hidden))
- rc |= print_ol(ol, US ol->name, d, d->info->options,
- *d->info->options_count, no_labels);
+ rc |= print_ol(ol, US ol->name, d, di->options,
+ *di->options_count, no_labels);
if (name) return rc;
}
static void
driver_init_fini(driver_instance * d, const uschar * class)
{
+driver_info * di = d->info;
+
if (!d->driver_name)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
"no driver defined for %s \"%s\"", class, d->name);
-(d->info->init)(d);
+(di->init)(d);
}
d = store_get_perm(instance_size, FALSE);
memcpy(d, instance_default, instance_size);
*p = d;
- p = &d->next;
+ p = (driver_instance **)&d->next;
d->name = string_copy(name);
d->srcfile = config_filename;
d->srcline = config_lineno;
block. */
else if (d->info)
- readconf_handle_option(buffer, d->info->options,
- *(d->info->options_count), d, US"option \"%s\" unknown");
+ {
+ driver_info * di = d->info;
+ readconf_handle_option(buffer, di->options,
+ *di->options_count, d, US"option \"%s\" unknown");
+ }
/* The option is not generic and the driver name has not yet been given. */
*/
BOOL
-readconf_depends(driver_instance *d, uschar *s)
+readconf_depends(driver_instance * d, uschar * s)
{
-int count = *(d->info->options_count);
-uschar *ss;
+driver_info * di = d->info;
+int count = *di->options_count;
+uschar * ss;
-for (optionlist * ol = d->info->options; ol < d->info->options + count; ol++)
+for (optionlist * ol = di->options; ol < di->options + count; ol++)
if ((ol->type & opt_mask) == opt_stringptr)
{
void * options_block = ol->type & opt_public ? (void *)d : d->options_block;
{ "domains", opt_stringptr|opt_public,
LOFF(domains) },
{ "driver", opt_stringptr|opt_public,
- LOFF(driver_name) },
+ LOFF(drinst.driver_name) },
{ "dsn_lasthop", opt_bool|opt_public,
LOFF(dsn_lasthop) },
{ "errors_to", opt_stringptr|opt_public,
options_from_list(optionlist_routers, nelem(optionlist_routers), US"ROUTERS", NULL);
-for (router_info * ri = routers_available; ri->driver_name[0]; ri++)
+for (router_info * ri = routers_available; ri->drinfo.driver_name[0]; ri++)
{
- spf(buf, sizeof(buf), US"_DRIVER_ROUTER_%T", ri->driver_name);
+ spf(buf, sizeof(buf), US"_DRIVER_ROUTER_%T", ri->drinfo.driver_name);
builtin_macro_create(buf);
- options_from_list(ri->options, (unsigned)*ri->options_count, US"ROUTER", ri->driver_name);
+ options_from_list(ri->drinfo.options, (unsigned)*ri->drinfo.options_count,
+ US"ROUTER", ri->drinfo.driver_name);
}
}
BOOL afterthis = FALSE;
router_instance *rr;
-for (rr = routers; rr; rr = rr->next)
+for (rr = routers; rr; rr = rr->drinst.next)
{
- if (Ustrcmp(name, rr->name) == 0)
+ if (Ustrcmp(name, rr->drinst.name) == 0)
{
*ptr = rr;
break;
if (!rr)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
- "new_router \"%s\" not found for \"%s\" router", name, r->name);
+ "new_router \"%s\" not found for \"%s\" router", name, r->drinst.name);
if (after && !afterthis)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
- "new_router \"%s\" does not follow \"%s\" router", name, r->name);
+ "new_router \"%s\" does not follow \"%s\" router", name, r->drinst.name);
}
optionlist_routers, /* generic options */
optionlist_routers_size);
-for (router_instance * r = routers; r; r = r->next)
+for (router_instance * r = routers; r; r = r->drinst.next)
{
- uschar *s = r->self;
+ uschar * s = r->self;
+ router_info * ri = r->drinst.info;
/* If log_as_local is unset, its overall default is FALSE. (The accept
router defaults it to TRUE.) */
/* Check for transport or no transport on certain routers */
- if ( (r->info->ri_flags & ri_yestransport)
- && !r->transport_name && !r->verify_only)
+ if (ri->ri_flags & ri_yestransport && !r->transport_name && !r->verify_only)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG, "%s router:\n "
- "a transport is required for this router", r->name);
+ "a transport is required for this router", r->drinst.name);
- if ((r->info->ri_flags & ri_notransport) && r->transport_name)
+ if (ri->ri_flags & ri_notransport && r->transport_name)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG, "%s router:\n "
- "a transport must not be defined for this router", r->name);
+ "a transport must not be defined for this router", r->drinst.name);
/* The "self" option needs to be decoded into a code value and possibly a
new domain string and a rewrite boolean. */
}
else log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n "
- "%s is not valid for the self option", r->name, s);
+ "%s is not valid for the self option", r->drinst.name, s);
/* If any router has check_local_user set, default retry_use_local_part
TRUE; otherwise its default is FALSE. */
void
route_tidyup(void)
{
-for (router_instance * r = routers; r; r = r->next)
- if (r->info->tidyup) (r->info->tidyup)(r);
+for (router_instance * r = routers; r; r = r->drinst.next)
+ {
+ router_info * ri = r->drinst.info;
+ if (ri->tidyup) (ri->tidyup)(r);
+ }
}
*/
static int
-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)
+route_check_dls(const uschar * rname, const uschar * type, const uschar * list,
+ tree_node ** anchorptr, unsigned int * cache_bits, int listtype,
+ const uschar * domloc, const uschar ** ldata, BOOL caseless, uschar ** perror)
{
if (!list) return OK; /* Empty list always succeeds */
int rc;
uschar * check_local_part;
unsigned int * localpart_cache;
+const uschar * rname = r->drinst.name;
/* Reset variables to hold a home directory and data from lookup of a domain or
local part, and ensure search_find_defer is unset, in case there aren't any
if ((verify == v_none || verify == v_expn) && r->verify_only)
{
- DEBUG(D_route) debug_printf("%s router skipped: verify_only set\n", r->name);
+ DEBUG(D_route) debug_printf("%s router skipped: verify_only set\n", rname);
return SKIP;
}
if (f.address_test_mode && !r->address_test)
{
DEBUG(D_route) debug_printf("%s router skipped: address_test is unset\n",
- r->name);
+ rname);
return SKIP;
}
(verify == v_recipient && !r->verify_recipient))
{
DEBUG(D_route) debug_printf("%s router skipped: verify %d %d %d\n",
- r->name, verify, r->verify_sender, r->verify_recipient);
+ rname, verify, r->verify_sender, r->verify_recipient);
return SKIP;
}
if (verify == v_expn && !r->expn)
{
- DEBUG(D_route) debug_printf("%s router skipped: no_expn set\n", r->name);
+ DEBUG(D_route) debug_printf("%s router skipped: no_expn set\n", rname);
return SKIP;
}
/* Skip this router if there's a domain mismatch. */
-if ((rc = route_check_dls(r->name, US"domains", r->domains, &domainlist_anchor,
+if ((rc = route_check_dls(rname, US"domains", r->domains, &domainlist_anchor,
addr->domain_cache, TRUE, addr->domain, CUSS &deliver_domain_data,
MCL_DOMAIN, perror)) != OK)
return rc;
check_local_part[Ustrlen(check_local_part) - Ustrlen(addr->suffix)] = 0;
}
-if ((rc = route_check_dls(r->name, US"local_parts", r->local_parts,
+if ((rc = route_check_dls(rname, US"local_parts", r->local_parts,
&localpartlist_anchor, localpart_cache, MCL_LOCALPART,
check_local_part, CUSS &deliver_localpart_data,
!r->caseful_local_part, perror)) != OK)
if (!route_finduser(addr->local_part, pw, NULL))
{
DEBUG(D_route) debug_printf("%s router skipped: %s is not a local user\n",
- r->name, addr->local_part);
+ rname, addr->local_part);
return SKIP;
}
addr->prop.localpart_data =
local user check so that $home is set - enabling the possibility of letting
individual recipients specify lists of acceptable/unacceptable senders. */
-if ((rc = route_check_dls(r->name, US"senders", r->senders, NULL,
+if ((rc = route_check_dls(rname, US"senders", r->senders, NULL,
sender_address_cache, MCL_ADDRESS, NULL, NULL, FALSE, perror)) != OK)
return rc;
if ((rc = check_files(r->require_files, perror)) != OK)
{
- DEBUG(D_route) debug_printf("%s router %s: file check\n", r->name,
+ DEBUG(D_route) debug_printf("%s router %s: file check\n", rname,
(rc == SKIP)? "skipped" : "deferred");
return rc;
}
{
DEBUG(D_route|D_expand)
debug_printf("checking \"condition\" \"%.80s\"...\n", r->condition);
- if (!expand_check_condition(r->condition, r->name, US"router"))
+ if (!expand_check_condition(r->condition, rname, US"router"))
{
if (f.search_find_defer)
{
return DEFER;
}
DEBUG(D_route)
- debug_printf("%s router skipped: condition failure\n", r->name);
+ debug_printf("%s router skipped: condition failure\n", rname);
return SKIP;
}
}
if (bmi_check_rule(bmi_base64_verdict, r->bmi_rule) == 0)
{ /* none of the rules fired */
DEBUG(D_route)
- debug_printf("%s router skipped: none of bmi_rule rules fired\n", r->name);
+ debug_printf("%s router skipped: none of bmi_rule rules fired\n", rname);
return SKIP;
}
}
if (r->bmi_dont_deliver && bmi_deliver == 1)
{
DEBUG(D_route)
- debug_printf("%s router skipped: bmi_dont_deliver is FALSE\n", r->name);
+ debug_printf("%s router skipped: bmi_dont_deliver is FALSE\n", rname);
return SKIP;
}
)
{
DEBUG(D_route)
- debug_printf("%s router skipped: bmi_deliver_alternate is FALSE\n", r->name);
+ debug_printf("%s router skipped: bmi_deliver_alternate is FALSE\n", rname);
return SKIP;
}
)
{
DEBUG(D_route)
- debug_printf("%s router skipped: bmi_deliver_default is FALSE\n", r->name);
+ debug_printf("%s router skipped: bmi_deliver_default is FALSE\n", rname);
return SKIP;
}
#endif
*/
static void
-route_unseen(uschar *name, address_item *addr, address_item **paddr_local,
- address_item **paddr_remote, address_item **addr_new)
+route_unseen(const uschar * name, address_item * addr,
+ address_item **paddr_local, address_item ** paddr_remote,
+ address_item ** addr_new)
{
address_item *parent = deliver_make_addr(addr->address, TRUE);
address_item *new = deliver_make_addr(addr->address, TRUE);
/* As it has turned out, we haven't set headers_add or headers_remove for the
- * clone. Thinking about it, it isn't entirely clear whether they should be
- * copied from the original parent, like errors_address, or taken from the
- * unseen router, like address_data and the flags. Until somebody brings this
- * up, I propose to leave the code as it is.
- */
+clone. Thinking about it, it isn't entirely clear whether they should be
+copied from the original parent, like errors_address, or taken from the
+unseen router, like address_data and the flags. Until somebody brings this
+up, I propose to leave the code as it is. */
/* Set the cloned address to start at the next router, and put it onto the
chain of new addresses. */
-new->start_router = addr->router->next;
+new->start_router = addr->router->drinst.next;
new->next = *addr_new;
*addr_new = new;
const uschar * varlist = r->set;
tree_node ** root = (tree_node **) &addr->prop.variables;
int sep = ';';
+const uschar * drname = r->drinst.name;
GET_OPTION("set");
if (!varlist) return OK;
if (!name || name[0] != 'r' || name[1] != '_' || !name[2])
{
log_write(0, LOG_MAIN|LOG_PANIC,
- "bad router variable name '%s' in router '%s'\n", name, r->name);
+ "bad router variable name '%s' in router '%s'\n", name, drname);
return FAIL;
}
name += 2;
/* Expand "more" if necessary; DEFER => an expansion failed */
GET_OPTION("more");
- yield = exp_bool(addr, US"router", r->name, D_route,
+ yield = exp_bool(addr, US"router", drname, D_route,
US"more", r->more, r->expand_more, &more);
if (yield != OK) return yield;
else
{
addr->message = string_sprintf("expansion of \"%s\" failed "
- "in %s router: %s", ele, r->name, expand_string_message);
+ "in %s router: %s", ele, drname, expand_string_message);
/* Caller will replace that for logging, if a DB lookup, to avoid exposing
passwords */
DEBUG(D_route) debug_printf("%s\n", addr->message);
BOOL unseen;
router_instance * r, * nextr;
const uschar * old_domain = addr->domain;
+const uschar * rname_l;
HDEBUG(D_route)
{
uschar * error;
struct passwd * pw = NULL;
struct passwd pwcopy;
- BOOL loop_detected = FALSE;
- BOOL more;
- int loopcount = 0;
- int rc;
+ BOOL loop_detected = FALSE, more;
+ int loopcount = 0, rc;
- DEBUG(D_route) debug_printf("--------> %s router <--------\n", r->name);
+ rname_l = r->drinst.name;
+ DEBUG(D_route) debug_printf("--------> %s router <--------\n", rname_l);
/* Reset any search error message from the previous router. */
next router. */
addr->router = r;
- nextr = r->next;
+ nextr = r->drinst.next;
/* Loop protection: If this address has an ancestor with the same address,
and that ancestor was routed by this router, we skip this router. This
if (break_loop)
{
DEBUG(D_route) debug_printf("%s router skipped: previously routed %s\n",
- r->name, parent->address);
+ rname_l, parent->address);
loop_detected = TRUE;
break;
}
}
else if (!r->prefix_optional)
{
- DEBUG(D_route) debug_printf("%s router skipped: prefix mismatch\n",
- r->name);
+ DEBUG(D_route)
+ debug_printf("%s router skipped: prefix mismatch\n", rname_l);
continue;
}
}
}
else if (!r->suffix_optional)
{
- DEBUG(D_route) debug_printf("%s router skipped: suffix mismatch\n",
- r->name);
+ DEBUG(D_route)
+ debug_printf("%s router skipped: suffix mismatch\n", rname_l);
continue;
}
}
/* Set the expansion variables now that we have the affixes and the case of
the local part sorted. */
- router_name = r->name;
- driver_srcfile = r->srcfile;
- driver_srcline = r->srcline;
+ router_name = rname_l;
+ driver_srcfile = r->drinst.srcfile;
+ driver_srcline = r->drinst.srcline;
deliver_set_expansions(addr);
/* For convenience, the pre-router checks are in a separate function, which
/* Expand "more" if necessary; DEFER => an expansion failed */
GET_OPTION("more");
- yield = exp_bool(addr, US"router", r->name, D_route,
+ yield = exp_bool(addr, US"router", rname_l, D_route,
US"more", r->more, r->expand_more, &more);
if (yield != OK) goto ROUTE_EXIT;
else
{
addr->message = string_sprintf("expansion of \"%s\" failed "
- "in %s router: %s", r->address_data, r->name, expand_string_message);
+ "in %s router: %s", r->address_data, rname_l, expand_string_message);
yield = DEFER;
goto ROUTE_EXIT;
}
/* Run the router, and handle the consequences. */
- HDEBUG(D_route) debug_printf("calling %s router\n", r->name);
+ HDEBUG(D_route) debug_printf("calling %s router\n", rname_l);
- yield = (r->info->code)(r, addr, pw, verify, paddr_local, paddr_remote,
- addr_new, addr_succeed);
+ {
+ router_info * ri = r->drinst.info;
+ yield = (ri->code)(r, addr, pw, verify, paddr_local, paddr_remote,
+ addr_new, addr_succeed);
+ }
driver_srcfile = router_name = NULL; driver_srcline = 0;
if (yield == FAIL)
{
- HDEBUG(D_route) debug_printf("%s router forced address failure\n", r->name);
+ HDEBUG(D_route) debug_printf("%s router forced address failure\n", rname_l);
goto ROUTE_EXIT;
}
)
&& (yield == OK || yield == PASS))
{
- addr->message = string_sprintf("%s router forced verify failure", r->name);
+ addr->message = string_sprintf("%s router forced verify failure", rname_l);
if (*paddr_remote == addr) *paddr_remote = addr->next;
if (*paddr_local == addr) *paddr_local = addr->next;
yield = FAIL;
HDEBUG(D_route)
{
- debug_printf("%s router %s for %s\n", r->name,
+ debug_printf("%s router %s for %s\n", rname_l,
yield == PASS ? "passed" : "declined", addr->address);
if (Ustrcmp(old_domain, addr->domain) != 0)
debug_printf("domain %s rewritten\n", old_domain);
/* Expand "more" if necessary */
GET_OPTION("more");
- yield = exp_bool(addr, US"router", r->name, D_route,
+ yield = exp_bool(addr, US"router", rname_l, D_route,
US"more", r->more, r->expand_more, &more);
if (yield != OK) goto ROUTE_EXIT;
else
if (!f.expand_string_forcedfail)
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
- "cannot_route_message in %s router: %s", addr->router->name,
+ "cannot_route_message in %s router: %s",
+ addr->router->drinst.name,
expand_string_message);
}
}
if (yield == DEFER)
{
HDEBUG(D_route) debug_printf("%s router: defer for %s\n message: %s\n",
- r->name, addr->address, addr->message ? addr->message : US"<none>");
+ rname_l, addr->address, addr->message ? addr->message : US"<none>");
goto ROUTE_EXIT;
}
if (yield != OK && yield != REROUTED)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s router returned unknown value %d",
- r->name, yield);
+ rname_l, yield);
/* If the yield was REROUTED, the router put a child address on the new chain
as a result of a domain change of some sort (widening, typically). */
/* 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, US"router", r->name, D_route,
+yield = exp_bool(addr, US"router", rname_l, D_route,
US"unseen", r->unseen, r->expand_unseen, &unseen);
if (yield != OK) goto ROUTE_EXIT;
/* Debugging output recording a successful routing */
-HDEBUG(D_route) debug_printf("routed by %s router%s\n", r->name,
- unseen? " (unseen)" : "");
+HDEBUG(D_route) debug_printf("routed by %s router%s\n", rname_l,
+ unseen ? " (unseen)" : "");
DEBUG(D_route)
{
the "unseen" option (ignore if there are no further routers). */
addr->message = NULL;
-if (unseen && r->next)
- route_unseen(r->name, addr, paddr_local, paddr_remote, addr_new);
+if (unseen && r->drinst.next)
+ route_unseen(rname_l, addr, paddr_local, paddr_remote, addr_new);
/* Unset the address expansions, and return the final result. */
#ifdef MACRO_PREDEF
/* Dummy entries */
-void accept_router_init(router_instance *rblock) {}
+void accept_router_init(driver_instance *rblock) {}
int accept_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,
/* Called for each instance, after its options have been read, to enable
consistency checks to be done, or anything else that needs to be set up. */
-void accept_router_init(router_instance *rblock)
+void
+accept_router_init(driver_instance * r)
{
+router_instance * rblock = (router_instance *)r;
/*
accept_router_options_block *ob =
(accept_router_options_block *)(rblock->options_block);
header_line * extra_headers;
DEBUG(D_route) debug_printf("%s router called for %s\n domain = %s\n",
- rblock->name, addr->address, addr->domain);
+ rblock->drinst.name, addr->address, addr->domain);
/* Set up the errors address, if any. */
verifying. */
if (!rf_get_transport(rblock->transport_name, &(rblock->transport),
- addr, rblock->name, NULL)) return DEFER;
+ addr, rblock->drinst.name, NULL)) return DEFER;
addr->transport = rblock->transport;
addr->prop.errors_address = errors_to;
struct passwd *, int, address_item **, address_item **,
address_item **, address_item **);
-extern void accept_router_init(router_instance *);
+extern void accept_router_init(driver_instance *);
/* End of routers/accept.h */
/* Dummy entries */
dnslookup_router_options_block dnslookup_router_option_defaults = {0};
-void dnslookup_router_init(router_instance *rblock) {}
+void dnslookup_router_init(driver_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,
consistency checks to be done, or anything else that needs to be set up. */
void
-dnslookup_router_init(router_instance *rblock)
+dnslookup_router_init(driver_instance *rblock)
{
/*
dnslookup_router_options_block *ob =
int widen_sep = 0;
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);
+ (dnslookup_router_options_block *)(rblock->drinst.options_block);
uschar * srv_service = NULL, * widen = NULL;
const uschar * pre_widen = addr->domain, * post_widen = NULL;
const uschar * fully_qualified_name, * listptr;
DEBUG(D_route)
debug_printf("%s router called for %s\n domain = %s\n",
- rblock->name, addr->address, addr->domain);
+ rblock->drinst.name, addr->address, addr->domain);
/* If an SRV check is required, expand the service name */
&& !f.expand_string_forcedfail)
{
addr->message = string_sprintf("%s router: failed to expand \"%s\": %s",
- rblock->name, ob->check_srv, expand_string_message);
+ rblock->drinst.name, ob->check_srv, expand_string_message);
return DEFER;
}
else
/* not expanded so should never be tainted */
widen = string_nextinlist(&listptr, &widen_sep, widen_buffer,
sizeof(widen_buffer));
- DEBUG(D_route) debug_printf("%s router widened %s to %s\n", rblock->name,
- addr->domain, h.name);
+ DEBUG(D_route) debug_printf("%s router widened %s to %s\n",
+ rblock->drinst.name, addr->domain, h.name);
}
else if (post_widen)
{
h.name = post_widen;
post_widen = NULL;
DEBUG(D_route) debug_printf("%s router trying %s after widening failed\n",
- rblock->name, h.name);
+ rblock->drinst.name, h.name);
}
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"))
+ && expand_check_condition(ob->ipv4_only, rblock->drinst.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"))
+ && expand_check_condition(ob->ipv4_prefer, rblock->drinst.name, US"router"))
flags |= HOST_FIND_IPV4_FIRST;
else if (f.search_find_defer)
return DEFER;
case OK:
DEBUG(D_route) debug_printf("%s router rejected %s: no MX record(s)\n",
- rblock->name, fully_qualified_name);
+ rblock->drinst.name, fully_qualified_name);
continue;
}
if (rblock->pass_on_timeout)
{
DEBUG(D_route) debug_printf("%s router timed out, and pass_on_timeout is set\n",
- rblock->name);
+ rblock->drinst.name);
return PASS;
}
addr->message = US"host lookup did not complete";
case OK:
DEBUG(D_route) debug_printf("%s router: matched fail_defer_domains\n",
- rblock->name);
+ rblock->drinst.name);
addr->message = US"missing MX, or all MXs point to missing A records,"
" and defer requested";
return DEFER;
/* Fill in the transport and queue the address for delivery. */
if (!rf_get_transport(rblock->transport_name, &(rblock->transport),
- addr, rblock->name, NULL))
+ addr, rblock->drinst.name, NULL))
return DEFER;
addr->transport = rblock->transport;
-return rf_queue_add(addr, addr_local, addr_remote, rblock, pw)?
- OK : DEFER;
+return rf_queue_add(addr, addr_local, addr_remote, rblock, pw) ? OK : DEFER;
}
#endif /*!MACRO_PREDEF*/
struct passwd *, int, address_item **, address_item **,
address_item **, address_item **);
-extern void dnslookup_router_init(router_instance *);
+extern void dnslookup_router_init(driver_instance *);
/* End of routers/dnslookup.h */
#ifdef MACRO_PREDEF
/* Dummy entries */
-void ipliteral_router_init(router_instance *rblock) {}
+void ipliteral_router_init(driver_instance *rblock) {}
int ipliteral_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,
consistency checks to be done, or anything else that needs to be set up. */
void
-ipliteral_router_init(router_instance *rblock)
+ipliteral_router_init(driver_instance *rblock)
{
/*
ipliteral_router_options_block *ob =
int rc, ipv;
DEBUG(D_route) debug_printf("%s router called for %s: domain = %s\n",
- rblock->name, addr->address, addr->domain);
+ rblock->drinst.name, addr->address, addr->domain);
/* Check that the domain is an IP address enclosed in square brackets. Remember
to allow for the "official" form of IPv6 addresses. If not, the router
which queue we put the address on. This is all now handled by the route_queue()
function. */
-if (!rf_get_transport(rblock->transport_name, &(rblock->transport),
- addr, rblock->name, NULL))
+if (!rf_get_transport(rblock->transport_name, &rblock->transport,
+ addr, rblock->drinst.name, NULL))
return DEFER;
addr->transport = rblock->transport;
struct passwd *, int, address_item **, address_item **,
address_item **, address_item **);
-extern void ipliteral_router_init(router_instance *);
+extern void ipliteral_router_init(driver_instance *);
/* End of routers/ipliteral.h */
/* Dummy entries */
manualroute_router_options_block manualroute_router_option_defaults = {0};
-void manualroute_router_init(router_instance *rblock) {}
+void manualroute_router_init(driver_instance *rblock) {}
int manualroute_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,
consistency checks to be done, or anything else that needs to be set up. */
void
-manualroute_router_init(router_instance *rblock)
+manualroute_router_init(driver_instance *rblock)
{
manualroute_router_options_block *ob =
(manualroute_router_options_block *)(rblock->options_block);
const uschar *domain;
uschar *newhostlist;
const uschar *listptr;
-manualroute_router_options_block *ob =
- (manualroute_router_options_block *)(rblock->options_block);
+manualroute_router_options_block * ob =
+ (manualroute_router_options_block *)(rblock->drinst.options_block);
transport_instance *transport = NULL;
BOOL individual_transport_set = FALSE;
BOOL randomize = ob->hosts_randomize;
DEBUG(D_route) debug_printf("%s router called for %s\n domain = %s\n",
- rblock->name, addr->address, addr->domain);
+ rblock->drinst.name, addr->address, addr->domain);
/* The initialization check ensures that either route_list or route_data is
set. */
{
if (f.expand_string_forcedfail) return DECLINE;
addr->message = string_sprintf("%s router: failed to expand \"%s\": %s",
- rblock->name, hostlist, expand_string_message);
+ rblock->drinst.name, hostlist, expand_string_message);
return DEFER;
}
else hostlist = newhostlist;
if (!t)
{
s = string_sprintf("unknown routing option or transport name \"%s\"", s);
- log_write(0, LOG_MAIN, "Error in %s router: %s", rblock->name, s);
+ log_write(0, LOG_MAIN, "Error in %s router: %s", rblock->drinst.name, s);
addr->message = string_sprintf("error in router: %s", s);
return DEFER;
}
if (!individual_transport_set)
{
- if (!rf_get_transport(rblock->transport_name, &(rblock->transport), addr,
- rblock->name, NULL))
+ if (!rf_get_transport(rblock->transport_name, &rblock->transport, addr,
+ rblock->drinst.name, NULL))
return DEFER;
transport = rblock->transport;
}
rf_queue_add() function. */
addr->transport = transport;
- return rf_queue_add(addr, addr_local, addr_remote, rblock, pw)?
- OK : DEFER;
+ return rf_queue_add(addr, addr_local, addr_remote, rblock, pw) ? OK : DEFER;
}
/* There is either no transport (verify_only) or a remote transport. A host
{
if (verify != v_none) goto ROUTED;
addr->message = string_sprintf("error in %s router: no host(s) specified "
- "for domain %s", rblock->name, addr->domain);
+ "for domain %s", rblock->drinst.name, addr->domain);
log_write(0, LOG_MAIN, "%s", addr->message);
return DEFER;
}
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]);
+ "host_find_failed=ignore host_all_ignored=%s",
+ rblock->drinst.name, hff_names[i]);
if (ob->hai_code == hff_defer) return DEFER;
if (ob->hai_code == hff_fail) return FAIL;
if (!transport && verify == v_none)
{
log_write(0, LOG_MAIN, "Error in %s router: no transport defined",
- rblock->name);
+ rblock->drinst.name);
addr->message = US"error in router: transport missing";
return DEFER;
}
struct passwd *, int, address_item **, address_item **,
address_item **, address_item **);
-extern void manualroute_router_init(router_instance *);
+extern void manualroute_router_init(driver_instance *);
/* End of routers/manualroute.h */
/* Dummy entries */
queryprogram_router_options_block queryprogram_router_option_defaults = {0};
-void queryprogram_router_init(router_instance *rblock) {}
+void queryprogram_router_init(driver_instance *rblock) {}
int queryprogram_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,
consistency checks to be done, or anything else that needs to be set up. */
void
-queryprogram_router_init(router_instance *rblock)
+queryprogram_router_init(driver_instance * rblock)
{
queryprogram_router_options_block *ob =
(queryprogram_router_options_block *)(rblock->options_block);
if (addr->child_count == USHRT_MAX)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s router generated more than %d "
- "child addresses for <%s>", rblock->name, USHRT_MAX, addr->address);
+ "child addresses for <%s>", rblock->drinst.name, USHRT_MAX, addr->address);
addr->child_count++;
DEBUG(D_route)
- debug_printf("%s router generated %s\n", rblock->name, next->address);
+ debug_printf("%s router generated %s\n", rblock->drinst.name, next->address);
}
}
const uschar **argvptr;
uschar *rword, *rdata, *s;
address_item_propagated addr_prop;
-queryprogram_router_options_block *ob =
- (queryprogram_router_options_block *)(rblock->options_block);
+queryprogram_router_options_block * ob =
+ (queryprogram_router_options_block *)(rblock->drinst.options_block);
uschar *current_directory = ob->current_directory;
ugid_block ugid;
uid_t curr_uid = getuid();
gid_t *pgid = &gid;
DEBUG(D_route) debug_printf("%s router called for %s: domain = %s\n",
- rblock->name, addr->address, addr->domain);
+ rblock->drinst.name, addr->address, addr->domain);
ugid.uid_set = ugid.gid_set = FALSE;
(initialization ensures that one or the other is set). */
if ( !ob->cmd_uid_set
- && !route_find_expanded_user(ob->expand_cmd_uid, rblock->name, US"router",
- &upw, &uid, &(addr->message)))
+ && !route_find_expanded_user(ob->expand_cmd_uid, rblock->drinst.name,
+ US"router", &upw, &uid, &(addr->message)))
return DEFER;
/* Get the fixed or expanded gid, or take the gid from the passwd entry. */
if (!ob->cmd_gid_set)
if (ob->expand_cmd_gid)
{
- if (route_find_expanded_group(ob->expand_cmd_gid, rblock->name,
+ if (route_find_expanded_group(ob->expand_cmd_gid, rblock->drinst.name,
US"router", &gid, &(addr->message)))
return DEFER;
}
else
{
addr->message = string_sprintf("command_user set without command_group "
- "for %s router", rblock->name);
+ "for %s router", rblock->drinst.name);
return DEFER;
}
current_directory, TRUE, US"queryprogram-cmd")) < 0)
{
addr->message = string_sprintf("%s router couldn't create child process: %s",
- rblock->name, strerror(errno));
+ rblock->drinst.name, strerror(errno));
return DEFER;
}
{
if (rc > 0)
addr->message = string_sprintf("%s router: command returned non-zero "
- "code %d", rblock->name, rc);
+ "code %d", rblock->drinst.name, rc);
else if (rc == -256)
{
addr->message = string_sprintf("%s router: command timed out",
- rblock->name);
+ rblock->drinst.name);
killpg(pid, SIGKILL); /* Kill the whole process group */
}
else if (rc == -257)
addr->message = string_sprintf("%s router: wait() failed: %s",
- rblock->name, strerror(errno));
+ rblock->drinst.name, strerror(errno));
else
addr->message = string_sprintf("%s router: command killed by signal %d",
- rblock->name, -rc);
+ rblock->drinst.name, -rc);
return DEFER;
}
if (len <= 0)
{
addr->message = string_sprintf("%s router: command failed to return data",
- rblock->name);
+ rblock->drinst.name);
return DEFER;
}
&addr->message, /* where to put messages */
NULL, /* don't skip syntax errors */
&filtertype, /* not used; will always be FILTER_FORWARD */
- string_sprintf("%s router", rblock->name));
+ string_sprintf("%s router", rblock->drinst.name));
switch (rc)
{
else if (strcmpic(rword, US"defer") != 0)
{
addr->message = string_sprintf("bad command yield: %s %s", rword, rdata);
- log_write(0, LOG_PANIC, "%s router: %s", rblock->name, addr->message);
+ log_write(0, LOG_PANIC, "%s router: %s", rblock->drinst.name, addr->message);
}
return DEFER;
}
{
addr->message = string_sprintf("unknown transport name %s yielded by "
"command", s);
- log_write(0, LOG_PANIC, "%s router: %s", rblock->name, addr->message);
+ log_write(0, LOG_PANIC, "%s router: %s", rblock->drinst.name, addr->message);
return DEFER;
}
addr->transport = transport;
else
{
if (!rf_get_transport(rblock->transport_name, &rblock->transport, addr,
- rblock->name, US"transport"))
+ rblock->drinst.name, US"transport"))
return DEFER;
addr->transport = rblock->transport;
}
{
addr->message = string_sprintf("bad lookup type \"%s\" yielded by "
"command", ss);
- log_write(0, LOG_PANIC, "%s router: %s", rblock->name, addr->message);
+ log_write(0, LOG_PANIC, "%s router: %s", rblock->drinst.name, addr->message);
return DEFER;
}
}
struct passwd *, int, address_item **, address_item **,
address_item **, address_item **);
-extern void queryprogram_router_init(router_instance *);
+extern void queryprogram_router_init(driver_instance *);
/* End of routers/queryprogram.h */
/* Dummy entries */
redirect_router_options_block redirect_router_option_defaults = {0};
-void redirect_router_init(router_instance *rblock) {}
+void redirect_router_init(driver_instance *rblock) {}
int redirect_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,
/* Called for each instance, after its options have been read, to enable
consistency checks to be done, or anything else that needs to be set up. */
-void redirect_router_init(router_instance *rblock)
+void
+redirect_router_init(driver_instance * r)
{
-redirect_router_options_block *ob =
- (redirect_router_options_block *)(rblock->options_block);
+router_instance * rblock = (router_instance *)r;
+redirect_router_options_block * ob =
+ (redirect_router_options_block *)(r->options_block);
/* Either file or data must be set, but not both */
if ((ob->file == NULL) == (ob->data == NULL))
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n "
"%sone of \"file\" or \"data\" must be specified",
- rblock->name, (ob->file == NULL)? "" : "only ");
+ r->name, ob->file ? "only " : "");
/* Onetime aliases can only be real addresses. Headers can't be manipulated.
The combination of one_time and unseen is not allowed. We can't check the
if (rblock->extra_headers || rblock->remove_headers)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n "
"\"headers_add\" and \"headers_remove\" are not permitted with "
- "\"one_time\"", rblock->name);
+ "\"one_time\"", r->name);
if (rblock->unseen || rblock->expand_unseen)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n "
- "\"unseen\" may not be used with \"one_time\"", rblock->name);
+ "\"unseen\" may not be used with \"one_time\"", r->name);
}
/* The defaults for check_owner and check_group depend on other settings. The
if (ob->qualify_domain && ob->qualify_preserve_domain)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n "
"only one of \"qualify_domain\" or \"qualify_preserve_domain\" must be set",
- rblock->name);
+ r->name);
/* If allow_filter is set, either user or check_local_user must be set. */
(ob->bit_options & RDO_FILTER) != 0)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n "
"\"user\" or \"check_local_user\" must be set with \"allow_filter\"",
- rblock->name);
+ r->name);
}
address_item *addr, address_item *generated,
address_item_propagated *addr_prop, ugid_block *ugidptr, struct passwd *pw)
{
-redirect_router_options_block *ob =
- (redirect_router_options_block *)(rblock->options_block);
+redirect_router_options_block * ob =
+ (redirect_router_options_block *)(rblock->drinst.options_block);
while (generated)
{
next->start_router = rblock->redirect_router;
if (addr->child_count == USHRT_MAX)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s router generated more than %d "
- "child addresses for <%s>", rblock->name, USHRT_MAX, addr->address);
+ "child addresses for <%s>", rblock->drinst.name, USHRT_MAX, addr->address);
addr->child_count++;
next->next = *addr_new;
address_pipe = next->address;
GET_OPTION("pipe_transport");
if (rf_get_transport(ob->pipe_transport_name, &ob->pipe_transport,
- next, rblock->name, US"pipe_transport"))
+ next, rblock->drinst.name, US"pipe_transport"))
next->transport = ob->pipe_transport;
address_pipe = NULL;
}
{
GET_OPTION("reply_transport");
if (rf_get_transport(ob->reply_transport_name, &ob->reply_transport,
- next, rblock->name, US"reply_transport"))
+ next, rblock->drinst.name, US"reply_transport"))
next->transport = ob->reply_transport;
}
else /* must be file or directory */
{
GET_OPTION("directory_transport");
if (rf_get_transport(ob->directory_transport_name,
- &(ob->directory_transport), next, rblock->name,
+ &ob->directory_transport, next, rblock->drinst.name,
US"directory_transport"))
next->transport = ob->directory_transport;
}
{
GET_OPTION("file_transport");
if (rf_get_transport(ob->file_transport_name, &ob->file_transport,
- next, rblock->name, US"file_transport"))
+ next, rblock->drinst.name, US"file_transport"))
next->transport = ob->file_transport;
}
DEBUG(D_route)
{
debug_printf("%s router generated %s\n %serrors_to=%s transport=%s\n",
- rblock->name,
+ rblock->drinst.name,
next->address,
testflag(next, af_pfr)? "pipe, file, or autoreply\n " : "",
next->prop.errors_address,
address_item **addr_new, /* put new addresses on here */
address_item **addr_succeed) /* put old address here on success */
{
-redirect_router_options_block *ob =
- (redirect_router_options_block *)(rblock->options_block);
+redirect_router_options_block * ob =
+ (redirect_router_options_block *)(rblock->drinst.options_block);
address_item *generated = NULL;
const uschar *save_qualify_domain_recipient = qualify_domain_recipient;
uschar *discarded = US"discarded";
if (!rf_get_ugid(rblock, addr, &ugid)) return DEFER;
-if (!ugid.uid_set && pw != NULL)
+if (!ugid.uid_set && pw)
{
ugid.uid = pw->pw_uid;
ugid.uid_set = TRUE;
}
-if (!ugid.gid_set && pw != NULL)
+if (!ugid.gid_set && pw)
{
ugid.gid = pw->pw_gid;
ugid.gid_set = TRUE;
frc = rda_interpret(&redirect, options, ob->include_directory, &sieve, &ugid,
&generated, &addr->message, ob->skip_syntax_errors ? &eblock : NULL,
- &filtertype, string_sprintf("%s router (recipient is %s)", rblock->name,
- addr->address));
+ &filtertype, string_sprintf("%s router (recipient is %s)",
+ rblock->drinst.name, addr->address));
qualify_domain_recipient = save_qualify_domain_recipient;
if (eblock != NULL)
{
if (!moan_skipped_syntax_errors(
- rblock->name, /* For message content */
+ rblock->drinst.name, /* For message content */
eblock, /* Ditto */
(verify != v_none || f.address_test_mode)?
NULL : ob->syntax_errors_to, /* Who to mail */
if (generated == NULL && verify == v_none && !f.address_test_mode)
{
log_write(0, LOG_MAIN, "=> %s <%s> R=%s", discarded, addr->address,
- rblock->name);
+ rblock->drinst.name);
yield = DISCARD;
}
}
next->prop = addr_prop;
DEBUG(D_route) debug_printf("%s router autogenerated %s\n%s%s%s",
- rblock->name,
+ rblock->drinst.name,
next->address,
(addr_prop.errors_address != NULL)? " errors to " : "",
(addr_prop.errors_address != NULL)? addr_prop.errors_address : US"",
struct passwd *, int, address_item **, address_item **,
address_item **, address_item **);
-extern void redirect_router_init(router_instance *);
+extern void redirect_router_init(driver_instance *);
/* End of routers/redirect.h */
return OK;
}
addr->message = string_sprintf("%s router failed to expand \"%s\": %s",
- rblock->name, rblock->errors_to, expand_string_message);
+ rblock->drinst.name, rblock->errors_to, expand_string_message);
return DEFER;
}
{
addr->message = string_sprintf(
"%s router failed to expand add_headers item \"%s\": %s",
- rblock->name, t, expand_string_message);
+ rblock->drinst.name, t, expand_string_message);
return DEFER;
}
}
{
addr->message = string_sprintf(
"%s router failed to expand remove_headers item \"%s\": %s",
- rblock->name, t, expand_string_message);
+ rblock->drinst.name, t, expand_string_message);
return DEFER;
}
}
/* If there is no fixed uid set, see if there's a dynamic one that can
be expanded and possibly looked up. */
-if (!ugid->uid_set && rblock->expand_uid != NULL)
+if (!ugid->uid_set && rblock->expand_uid)
{
- if (route_find_expanded_user(rblock->expand_uid, rblock->name, US"router",
- &upw, &(ugid->uid), &(addr->message))) ugid->uid_set = TRUE;
- else return FALSE;
+ if (!route_find_expanded_user(rblock->expand_uid, rblock->drinst.name,
+ US"router", &upw, &ugid->uid, &addr->message))
+ return FALSE;
+ ugid->uid_set = TRUE;
}
/* Likewise for the gid */
-if (!ugid->gid_set && rblock->expand_gid != NULL)
+if (!ugid->gid_set && rblock->expand_gid)
{
- if (route_find_expanded_group(rblock->expand_gid, rblock->name, US"router",
- &(ugid->gid), &(addr->message))) ugid->gid_set = TRUE;
- else return FALSE;
+ if (!route_find_expanded_group(rblock->expand_gid, rblock->drinst.name,
+ US"router", &ugid->gid, &addr->message))
+ return FALSE;
+ ugid->gid_set = TRUE;
}
/* If a uid is set, then a gid must also be available; use one from the passwd
if (ugid->uid_set && !ugid->gid_set)
{
- if (upw != NULL)
+ if (upw)
{
ugid->gid = upw->pw_gid;
ugid->gid_set = TRUE;
else
{
addr->message = string_sprintf("user set without group for %s router",
- rblock->name);
+ rblock->drinst.name);
return FALSE;
}
}
{
DEBUG(D_route)
debug_printf("%s router timed out and pass_on_timeout set\n",
- rblock->name);
+ rblock->drinst.name);
return PASS;
}
addr->message = string_sprintf("host lookup for %s did not complete "
addr->basic_errno = ERRNO_UNKNOWNHOST;
addr->message =
string_sprintf("lookup of host \"%s\" failed in %s router%s",
- h->name, rblock->name,
+ h->name, rblock->drinst.name,
f.host_find_failed_syntax? ": syntax error in name" : "");
if (hff_code == hff_defer) return DEFER;
by the generic structures driver_info and driver_instance. */
typedef struct driver_instance {
- struct driver_instance *next;
+ void *next;
uschar *name; /* Instance name */
- struct driver_info *info; /* Points to info for this driver */
+ void *info; /* Points to info for this driver */
void *options_block; /* Pointer to private options */
uschar *driver_name; /* All start with this generic option */
void *options_block; /* Points to default private block */
int options_len; /* Length of same in bytes */
void (*init)( /* Initialization entry point */
- struct driver_instance *);
+ struct driver_instance *);
} driver_info;
/* Structure for holding information about the configured routers. */
typedef struct router_instance {
- struct router_instance *next;
- uschar *name;
- struct router_info *info;
- void *options_block; /* Pointer to private options */
- uschar *driver_name; /* Must be first */
- const uschar *srcfile;
- int srcline;
+ driver_instance drinst;
uschar *address_data; /* Arbitrary data */
#ifdef EXPERIMENTAL_BRIGHTMAIL
} router_instance;
-/* Structure for holding information about a type of router. The first six
-fields must match driver_info above. */
+/* Structure for holding information about a type of router. The first element
+must be a struct driver_info, to match auths and transports. */
typedef struct router_info {
- uschar *driver_name;
- optionlist *options; /* Table of private options names */
- int *options_count; /* -> Number of entries in table */
- void *options_block; /* Points to default private block */
- int options_len; /* Length of same in bytes */
- void (*init)( /* Initialization function */
- struct router_instance *);
-/****/
+ driver_info drinfo;
+
int (*code)( /* Main entry point */
router_instance *,
struct address_item *,
{
uschar * action = addr->transport->event_action;
const uschar * save_domain, * save_local;
-uschar * save_rn, * save_tn;
+const uschar * save_rn;
+uschar * save_tn;
if (!action)
return;
deliver_host_port = host->port == PORT_NONE ? 25 : host->port;
event_defer_errno = addr->basic_errno;
-router_name = addr->router->name;
+router_name = addr->router->drinst.name;
transport_name = addr->transport->name;
deliver_domain = addr->domain;
deliver_localpart = addr->local_part;
/* Show router, and transport */
fprintf(fp, "router = %s, transport = %s\n",
- addr->router->name, tp ? tp->name : US"unset");
+ addr->router->drinst.name, tp ? tp->name : US"unset");
/* Show any hosts that are set up by a router unless the transport
is going to override them; fiddle a bit to get a nice format. */