summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhilip Hazel <ph10@hermes.cam.ac.uk>2005-03-22 14:11:54 +0000
committerPhilip Hazel <ph10@hermes.cam.ac.uk>2005-03-22 14:11:54 +0000
commit1a46a8c5c398c91f20c3f4def0ceb448ec8de96a (patch)
tree511495f754f5483f2645ab05cfb6dfb6d77f5c6e /src
parent8d67ada3e036ae1b48d7f20a82af42f9e52b810d (diff)
1. Added Tony F's ${dlfunc expansion, slightly modified (see NewStuff).
2. Recognize ${perl even if not compiled, and give suitable error message.
Diffstat (limited to 'src')
-rw-r--r--src/ACKNOWLEDGMENTS23
-rw-r--r--src/src/EDITME11
-rw-r--r--src/src/config.h.defaults5
-rw-r--r--src/src/exim.c5
-rw-r--r--src/src/exim.h8
-rw-r--r--src/src/expand.c119
-rw-r--r--src/src/globals.c6
-rw-r--r--src/src/globals.h6
-rw-r--r--src/src/local_scan.h22
-rw-r--r--src/src/macros.h43
-rw-r--r--src/src/routers/redirect.c6
11 files changed, 200 insertions, 54 deletions
diff --git a/src/ACKNOWLEDGMENTS b/src/ACKNOWLEDGMENTS
index 8314c699a..0982973d2 100644
--- a/src/ACKNOWLEDGMENTS
+++ b/src/ACKNOWLEDGMENTS
@@ -1,4 +1,4 @@
-$Cambridge: exim/src/ACKNOWLEDGMENTS,v 1.15 2005/03/15 12:27:54 ph10 Exp $
+$Cambridge: exim/src/ACKNOWLEDGMENTS,v 1.16 2005/03/22 14:11:54 ph10 Exp $
EXIM ACKNOWLEDGEMENTS
@@ -20,7 +20,7 @@ relatively small patches.
Philip Hazel
Lists created: 20 November 2002
-Last updated: 15 March 2005
+Last updated: 22 March 2005
THE OLD LIST
@@ -78,7 +78,7 @@ Richard Birkett Fix for empty -f address crash
Nick Burrett Patch for CONFIGURE_FILE_USE_EUID in exicyclog
Matthew Byng-Maddick Patch for qualify_domain in redirect router
Patch for ignore_target_hosts in ipliteral router
- The cyrus_sasl authenticator
+ The cyrus_sasl authenticator
Steve Campbell eximstats extensions and continued maintenance
Brian Candler Use h_errno for gethostbyname()
Suggested patch for .ifdef etc
@@ -93,7 +93,7 @@ Andrew Doran Patch for NetBSD configuration files
Patch for ifreq alignment and size problems
Michael Deutschmann Suggested patch for treating bind() failure like connect()
Patch for $sender_data and $recipient_data
- Suggested patch for null address match lookup bug
+ Suggested patch for null address match lookup bug
Oliver Eikemeier Patch to skip Received: if expansion is empty
Patch for "eqi"
Nico Erfurth Fix for bug in ${readfile}
@@ -121,9 +121,10 @@ Tony Finch Expansion extensions
A number of useful code criticisms
Timezone patch for exiwhat
Patch for more daemon exiwhat information
- Patch for -dd
- Patch for mxh lookup type in dnsdb
- Patch for defer_foo in dndsb
+ Patch for -dd
+ Patch for mxh lookup type in dnsdb
+ Patch for defer_foo in dndsb
+ Patch for ${dlfunc
Giuliano Gavazzi Patches for OSX compilation
Dominic Germain Patch for exiqgrep MacOS X bug
Oliver Gorwits $load_average patch
@@ -138,7 +139,7 @@ Michael Haardt Tidies to make the code stricter
Module to support Sieve (RFC 3028) filters and
continued maintenance of same
Patch for faster sort algorithm in queue.c
- Patch for LDAP timeout handling
+ Patch for LDAP timeout handling
Thomas Hager Patch for saslauthd crash bug
Richard Hall Fix for file descriptor leak in redirection
Steve Haslam Lots of stuff, including
@@ -154,7 +155,7 @@ Christian Kellner Patch for LDAP dereferencing
Alex Kiernan Patch for libradius
Diagnosis of milliwait clock-backwards bug
Tom Kistner SPA server code
- Writing and maintaining the content scanning
+ Writing and maintaining the content scanning
extension (exiscan)
Friso Kuipers Patch for GDBM problem
Chris Liddiard Fix for bug in exiqsumm
@@ -174,9 +175,9 @@ Marc Merlin Many suggestions and patches for callouts and
SMTP error message features
Andreas Metzler Patch for message_id_header_domain
Suggested patch for multi-config files in scripts bug
-Alex Miller Suggested readline() patch
+Alex Miller Suggested readline() patch
Patch for LDAP_RES_SEARCH_REFERENCE handling
- Support for the DrWeb content scanner
+ Support for the DrWeb content scanner
Andreas Mueller Patch for logging uncompleted SMTP transactions
Pete Naylor Patch for LDAP TCP connect timeout setting
Marcin Owsiany Diagnosis of a tricky timeout failure bug
diff --git a/src/src/EDITME b/src/src/EDITME
index 60774cf49..72f797bb3 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -1,4 +1,4 @@
-# $Cambridge: exim/src/src/EDITME,v 1.8 2005/02/17 11:58:25 ph10 Exp $
+# $Cambridge: exim/src/src/EDITME,v 1.9 2005/03/22 14:11:54 ph10 Exp $
##################################################
# The Exim mail transport agent #
@@ -690,6 +690,15 @@ ZCAT_COMMAND=/usr/bin/zcat
#------------------------------------------------------------------------------
+# Support for dynamically-loaded string expansion functions via ${dlfunc. If
+# you are using gcc the dynamically-loaded object must be compiled with the
+# -shared option, and you will need to add -export-dynamic to EXTRALIBS so
+# that the local_scan API is made available by the linker.
+
+# EXPAND_DLFUNC=yes
+
+
+#------------------------------------------------------------------------------
# Exim has support for PAM (Pluggable Authentication Modules), a facility
# which is available in the latest releases of Solaris and in some GNU/Linux
# distributions (see http://ftp.kernel.org/pub/linux/libs/pam/). The Exim
diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
index ea63c888f..2825f98c1 100644
--- a/src/src/config.h.defaults
+++ b/src/src/config.h.defaults
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/config.h.defaults,v 1.5 2005/03/08 15:32:02 tom Exp $ */
+/* $Cambridge: exim/src/src/config.h.defaults,v 1.6 2005/03/22 14:11:54 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -42,11 +42,10 @@ in config.h unless some value is defined in Local/Makefile. */
#define EXIMDB_LOCK_TIMEOUT 60
#define EXIMDB_LOCKFILE_MODE 0640
#define EXIMDB_MODE 0640
-
#define EXIM_PERL
-
/* Both uid and gid are triggered by this */
#define EXIM_UID
+#define EXPAND_DLFUNC
#define FIXED_NEVER_USERS "root"
diff --git a/src/src/exim.c b/src/src/exim.c
index 14cd03228..ffe596d15 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/exim.c,v 1.16 2005/03/15 14:09:12 ph10 Exp $ */
+/* $Cambridge: exim/src/src/exim.c,v 1.17 2005/03/22 14:11:54 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -829,6 +829,9 @@ fprintf(f, "Support for:");
#ifdef EXIM_PERL
fprintf(f, " Perl");
#endif
+#ifdef EXPAND_DLFUNC
+ fprintf(f, " Expand_dlfunc");
+#endif
#ifdef USE_TCP_WRAPPERS
fprintf(f, " TCPwrappers");
#endif
diff --git a/src/src/exim.h b/src/src/exim.h
index 42f7980c2..b28edb79b 100644
--- a/src/src/exim.h
+++ b/src/src/exim.h
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/exim.h,v 1.9 2005/03/15 14:09:12 ph10 Exp $ */
+/* $Cambridge: exim/src/src/exim.h,v 1.10 2005/03/22 14:11:54 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -60,7 +60,7 @@ making unique names. */
/* Unix includes */
#include <errno.h>
-#if defined(__svr4__) && defined(__sparc) && ! defined(__EXTENSIONS__)
+#if defined(__svr4__) && defined(__sparc) && ! defined(__EXTENSIONS__)
#define __EXTENSIONS__ /* so that SunOS 5 gets NGROUPS_MAX */
#include <limits.h>
#undef __EXTENSIONS__
@@ -207,7 +207,7 @@ or a macro with entries f_frsize and f_bsize. */
#endif
-#ifndef SIOCGIFCONF /* HACK for SunOS 5 */
+#ifndef SIOCGIFCONF /* HACK for SunOS 5 */
#include <sys/sockio.h>
#endif
@@ -414,7 +414,7 @@ requires various things that are set therein. */
#include <iconv.h>
#endif
-#ifdef USE_READLINE
+#if defined(USE_READLINE) || defined(EXPAND_DLFUNC)
#include <dlfcn.h>
#endif
diff --git a/src/src/expand.c b/src/src/expand.c
index 6e7d3550f..d27530bd7 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/expand.c,v 1.16 2005/03/09 08:27:51 tom Exp $ */
+/* $Cambridge: exim/src/src/expand.c,v 1.17 2005/03/22 14:11:54 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -48,6 +48,7 @@ static uschar *expand_string_internal(uschar *, BOOL, uschar **, BOOL);
alphabetical order. */
static uschar *item_table[] = {
+ US"dlfunc",
US"extract",
US"hash",
US"hmac",
@@ -55,9 +56,7 @@ static uschar *item_table[] = {
US"length",
US"lookup",
US"nhash",
- #ifdef EXIM_PERL
- US"perl",
- #endif
+ US"perl",
US"readfile",
US"readsocket",
US"run",
@@ -66,6 +65,7 @@ static uschar *item_table[] = {
US"tr" };
enum {
+ EITEM_DLFUNC,
EITEM_EXTRACT,
EITEM_HASH,
EITEM_HMAC,
@@ -73,9 +73,7 @@ enum {
EITEM_LENGTH,
EITEM_LOOKUP,
EITEM_NHASH,
- #ifdef EXIM_PERL
- EITEM_PERL,
- #endif
+ EITEM_PERL,
EITEM_READFILE,
EITEM_READSOCK,
EITEM_RUN,
@@ -3072,10 +3070,15 @@ while (*s != 0)
or ${perl{sub}{arg1}{arg2}} or up to a maximum of EXIM_PERL_MAX_ARGS
arguments (defined below). */
- #ifdef EXIM_PERL
#define EXIM_PERL_MAX_ARGS 8
case EITEM_PERL:
+ #ifndef EXIM_PERL
+ expand_string_message = US"\"${perl\" encountered, but this facility "
+ "is not included in this binary";
+ goto EXPAND_FAILED;
+
+ #else /* EXIM_PERL */
{
uschar *sub_arg[EXIM_PERL_MAX_ARGS + 2];
uschar *new_yield;
@@ -3847,6 +3850,106 @@ while (*s != 0)
continue;
}
+
+
+ /* If ${dlfunc support is configured, handle calling dynamically-loaded
+ functions, unless locked out at this time. Syntax is ${dlfunc{file}{func}}
+ or ${dlfunc{file}{func}{arg}} or ${dlfunc{file}{func}{arg1}{arg2}} or up to
+ a maximum of EXPAND_DLFUNC_MAX_ARGS arguments (defined below). */
+
+ #define EXPAND_DLFUNC_MAX_ARGS 8
+
+ case EITEM_DLFUNC:
+ #ifndef EXPAND_DLFUNC
+ expand_string_message = US"\"${dlfunc\" encountered, but this facility "
+ "is not included in this binary";
+ goto EXPAND_FAILED;
+
+ #else /* EXPAND_DLFUNC */
+ {
+ tree_node *t;
+ exim_dlfunc_t *func;
+ uschar *result;
+ int status, argc;
+ uschar *argv[EXPAND_DLFUNC_MAX_ARGS + 3];
+
+ if ((expand_forbid & RDO_DLFUNC) != 0)
+ {
+ expand_string_message =
+ US"dynamically-loaded functions are not permitted";
+ goto EXPAND_FAILED;
+ }
+
+ switch(read_subs(argv, EXPAND_DLFUNC_MAX_ARGS + 2, 2, &s, skipping,
+ TRUE, US"dlfunc"))
+ {
+ case 1: goto EXPAND_FAILED_CURLY;
+ case 2:
+ case 3: goto EXPAND_FAILED;
+ }
+
+ /* If skipping, we don't actually do anything */
+
+ if (skipping) continue;
+
+ /* Look up the dynamically loaded object handle in the tree. If it isn't
+ found, dlopen() the file and put the handle in the tree for next time. */
+
+ t = tree_search(dlobj_anchor, argv[0]);
+ if (t == NULL)
+ {
+ void *handle = dlopen(CS argv[0], RTLD_LAZY);
+ if (handle == NULL)
+ {
+ expand_string_message = string_sprintf("dlopen \"%s\" failed: %s",
+ argv[0], dlerror());
+ log_write(0, LOG_MAIN|LOG_PANIC, "%s", expand_string_message);
+ goto EXPAND_FAILED;
+ }
+ t = store_get_perm(sizeof(tree_node) + Ustrlen(argv[0]));
+ Ustrcpy(t->name, argv[0]);
+ t->data.ptr = handle;
+ (void)tree_insertnode(&dlobj_anchor, t);
+ }
+
+ /* Having obtained the dynamically loaded object handle, look up the
+ function pointer. */
+
+ func = (exim_dlfunc_t *)dlsym(t->data.ptr, CS argv[1]);
+ if (func == NULL)
+ {
+ expand_string_message = string_sprintf("dlsym \"%s\" in \"%s\" failed: "
+ "%s", argv[1], argv[0], dlerror());
+ log_write(0, LOG_MAIN|LOG_PANIC, "%s", expand_string_message);
+ goto EXPAND_FAILED;
+ }
+
+ /* Call the function and work out what to do with the result. If it
+ returns OK, we have a replacement string; if it returns DEFER then
+ expansion has failed in a non-forced manner; if it returns FAIL then
+ failure was forced; if it returns ERROR or any other value there's a
+ problem, so panic slightly. */
+
+ result = NULL;
+ for (argc = 0; argv[argc] != NULL; argc++);
+ status = func(&result, argc - 2, &argv[2]);
+ if(status == OK)
+ {
+ if (result == NULL) result = US"";
+ yield = string_cat(yield, &size, &ptr, result, Ustrlen(result));
+ continue;
+ }
+ else
+ {
+ expand_string_message = result == NULL ? US"(no message)" : result;
+ if(status == FAIL_FORCED) expand_string_forcedfail = TRUE;
+ else if(status != FAIL)
+ log_write(0, LOG_MAIN|LOG_PANIC, "dlfunc{%s}{%s} failed (%d): %s",
+ argv[0], argv[1], status, expand_string_message);
+ goto EXPAND_FAILED;
+ }
+ }
+ #endif /* EXPAND_DLFUNC */
}
/* Control reaches here if the name is not recognized as one of the more
diff --git a/src/src/globals.c b/src/src/globals.c
index fdccc0b98..2324e4072 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.c,v 1.19 2005/03/08 15:32:02 tom Exp $ */
+/* $Cambridge: exim/src/src/globals.c,v 1.20 2005/03/22 14:11:54 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -62,6 +62,10 @@ BOOL opt_perl_at_start = FALSE;
BOOL opt_perl_started = FALSE;
#endif
+#ifdef EXPAND_DLFUNC
+tree_node *dlobj_anchor = NULL;
+#endif
+
#ifdef LOOKUP_IBASE
uschar *ibase_servers = NULL;
#endif
diff --git a/src/src/globals.h b/src/src/globals.h
index 2bb61c145..404838126 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.h,v 1.12 2005/03/08 15:32:02 tom Exp $ */
+/* $Cambridge: exim/src/src/globals.h,v 1.13 2005/03/22 14:11:54 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -26,6 +26,10 @@ extern BOOL opt_perl_at_start; /* Start Perl interpreter at start */
extern BOOL opt_perl_started; /* Set once interpreter started */
#endif
+#ifdef EXPAND_DLFUNC
+extern tree_node *dlobj_anchor; /* Tree of dynamically-loaded objects */
+#endif
+
#ifdef LOOKUP_IBASE
extern uschar *ibase_servers;
#endif
diff --git a/src/src/local_scan.h b/src/src/local_scan.h
index e612ccd84..fdc73bed5 100644
--- a/src/src/local_scan.h
+++ b/src/src/local_scan.h
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/local_scan.h,v 1.3 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/local_scan.h,v 1.4 2005/03/22 14:11:54 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -9,7 +9,9 @@
/* This file is the header that is the only Exim header to be included in the
source for the local_scan.c() function. It contains definitions that are made
-available for use in that function, and which are documented. */
+available for use in that function, and which are documented.
+
+This API is also used for functions called by the ${dlfunc expansion item. */
/* Some basic types that make some things easier, and the store functions. */
@@ -34,13 +36,27 @@ enum {
};
-/* Return codes from the support functions lss_match_xxx(). */
+/* Functions called by ${dlfunc{file}{func}{arg}...} return one of the five
+status codes defined immediately below. The function's first argument is either
+the result of expansion, or the error message in case of failure. The second
+and third arguments are standard argument count and vector, comprising the
+{arg} values specified in the expansion item. */
+
+typedef int exim_dlfunc_t(uschar **yield, int argc, uschar *argv[]);
+
+
+/* Return codes from the support functions lss_match_xxx(). These are also the
+codes that dynamically-loaded ${dlfunc functions must return. */
#define OK 0 /* Successful match */
#define DEFER 1 /* Defer - some problem */
#define FAIL 2 /* Matching failed */
#define ERROR 3 /* Internal or config error */
+/* Extra return code for ${dlfunc functions */
+
+#define FAIL_FORCED 4 /* "Forced" failure */
+
/* Available logging destinations */
diff --git a/src/src/macros.h b/src/src/macros.h
index d69da22f7..86bb84f12 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/macros.h,v 1.10 2005/03/10 08:56:03 tom Exp $ */
+/* $Cambridge: exim/src/src/macros.h,v 1.11 2005/03/22 14:11:54 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -237,27 +237,29 @@ enum {
apply to all of them). Some other functions also use these convenient values,
and some additional values are used only by non-driver functions.
-OK, FAIL, DEFER, and ERROR are also declared in local_scan.h for use in the
-local_scan() function. Do not change them unilaterally. */
+OK, FAIL, DEFER, ERROR, and FAIL_FORCED are also declared in local_scan.h for
+use in the local_scan() function and in ${dlfunc loaded functions. Do not
+change them unilaterally. */
#define OK 0 /* Successful match */
#define DEFER 1 /* Defer - some problem */
#define FAIL 2 /* Matching failed */
#define ERROR 3 /* Internal or config error */
+#define FAIL_FORCED 4 /* "Forced" failure */
/***********/
-#define DECLINE 4 /* Declined to handle the address, pass to next
+#define DECLINE 5 /* Declined to handle the address, pass to next
router unless no_more is set */
-#define PASS 5 /* Pass to next driver, or to pass_router,
+#define PASS 6 /* Pass to next driver, or to pass_router,
even if no_more is set */
-#define DISCARD 6 /* Address routed to :blackhole: or "seen finish" */
-#define SKIP 7 /* Skip this router (used in route_address only) */
-#define REROUTED 8 /* Address was changed and child created*/
-#define PANIC 9 /* Hard failed with internal error */
-#define BAD64 10 /* Bad base64 data (auth) */
-#define UNEXPECTED 11 /* Unexpected initial auth data */
-#define CANCELLED 12 /* Authentication cancelled */
-#define FAIL_SEND 13 /* send() failed in authenticator */
-#define FAIL_DROP 14 /* Fail and drop connection (used in ACL) */
+#define DISCARD 7 /* Address routed to :blackhole: or "seen finish" */
+#define SKIP 8 /* Skip this router (used in route_address only) */
+#define REROUTED 9 /* Address was changed and child created*/
+#define PANIC 10 /* Hard failed with internal error */
+#define BAD64 11 /* Bad base64 data (auth) */
+#define UNEXPECTED 12 /* Unexpected initial auth data */
+#define CANCELLED 13 /* Authentication cancelled */
+#define FAIL_SEND 14 /* send() failed in authenticator */
+#define FAIL_DROP 15 /* Fail and drop connection (used in ACL) */
/* Returns from the deliver_message() function */
@@ -489,15 +491,16 @@ router, which were chosen to represent the standard situation for users'
#define RDO_READFILE 0x00001000 /* Forbid "readfile" in exp in filter */
#define RDO_READSOCK 0x00002000 /* Forbid "readsocket" in exp in filter */
#define RDO_RUN 0x00004000 /* Forbid "run" in expansion in filter */
-#define RDO_REALLOG 0x00008000 /* Really do log (not testing/verifying) */
-#define RDO_REWRITE 0x00010000 /* Rewrite generated addresses */
-#define RDO_EXIM_FILTER 0x00020000 /* Forbid Exim filters */
-#define RDO_SIEVE_FILTER 0x00040000 /* Forbid Sieve filters */
+#define RDO_DLFUNC 0x00008000 /* Forbid "dlfunc" in expansion in filter */
+#define RDO_REALLOG 0x00010000 /* Really do log (not testing/verifying) */
+#define RDO_REWRITE 0x00020000 /* Rewrite generated addresses */
+#define RDO_EXIM_FILTER 0x00040000 /* Forbid Exim filters */
+#define RDO_SIEVE_FILTER 0x00080000 /* Forbid Sieve filters */
/* This is the set that apply to expansions in filters */
#define RDO_FILTER_EXPANSIONS \
- (RDO_EXISTS|RDO_LOOKUP|RDO_PERL|RDO_READFILE|RDO_READSOCK|RDO_RUN)
+ (RDO_EXISTS|RDO_LOOKUP|RDO_PERL|RDO_READFILE|RDO_READSOCK|RDO_RUN|RDO_DLFUNC)
/* As well as the RDO bits themselves, we need the bit numbers in order to
access (most of) the individual bits as separate options. This could be
@@ -505,7 +508,7 @@ automated, but I haven't bothered. Keep this list in step with the above! */
enum { RDON_BLACKHOLE, RDON_DEFER, RDON_EACCES, RDON_ENOTDIR, RDON_EXISTS,
RDON_FAIL, RDON_FILTER, RDON_FREEZE, RDON_INCLUDE, RDON_LOG, RDON_LOOKUP,
- RDON_PERL, RDON_READFILE, RDON_READSOCK, RDON_RUN, RDON_REALLOG,
+ RDON_PERL, RDON_READFILE, RDON_READSOCK, RDON_RUN, RDON_DLFUNC, RDON_REALLOG,
RDON_REWRITE, RDON_EXIM_FILTER, RDON_SIEVE_FILTER };
/* Results of filter or forward file processing. Some are only from a filter;
diff --git a/src/src/routers/redirect.c b/src/src/routers/redirect.c
index 461fc5d92..65b5e4099 100644
--- a/src/src/routers/redirect.c
+++ b/src/src/routers/redirect.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/routers/redirect.c,v 1.6 2005/03/15 11:37:21 ph10 Exp $ */
+/* $Cambridge: exim/src/src/routers/redirect.c,v 1.7 2005/03/22 14:11:55 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -45,6 +45,10 @@ optionlist redirect_router_options[] = {
(void *)offsetof(redirect_router_options_block, bit_options) },
{ "forbid_file", opt_bool,
(void *)offsetof(redirect_router_options_block, forbid_file) },
+ #ifdef EXPAND_DLFUNC
+ { "forbid_filter_dlfunc", opt_bit | (RDON_DLFUNC << 16),
+ (void *)offsetof(redirect_router_options_block, bit_options) },
+ #endif
{ "forbid_filter_existstest", opt_bit | (RDON_EXISTS << 16),
(void *)offsetof(redirect_router_options_block, bit_options) },
{ "forbid_filter_logwrite",opt_bit | (RDON_LOG << 16),