Hi,
This patch is based on the original code by Titus Jose on GitHub, I
updated it to work with the development branch and have added some
documentation.
Duncan Bellamy
--- a/conf/dynamicmaps.cf 2014-05-30 12:38:33.000000000 +0100
+++ b/conf/dynamicmaps.cf 2020-09-23 20:42:28.001667576 +0100
@@ -5,5 +5,6 @@ lmdb ${LIB_PREFIX}lmdb${LIB_SUFFIX} dict
mysql ${LIB_PREFIX}mysql${LIB_SUFFIX} dict_mysql_open
pcre ${LIB_PREFIX}pcre${LIB_SUFFIX} dict_pcre_open
pgsql ${LIB_PREFIX}pgsql${LIB_SUFFIX} dict_pgsql_open
+redis ${LIB_PREFIX}redis${LIB_SUFFIX} dict_redis_open
sdbm ${LIB_PREFIX}sdbm${LIB_SUFFIX} dict_sdbm_open mkmap_sdbm_open
sqlite ${LIB_PREFIX}sqlite${LIB_SUFFIX} dict_sqlite_open
diff -Nurp a/conf/postfix-files b/conf/postfix-files
--- a/conf/postfix-files 2019-01-29 22:24:42.000000000 +0000
+++ b/conf/postfix-files 2020-09-23 20:48:19.527925031 +0100
@@ -78,6 +78,7 @@ $shlib_directory/${LIB_PREFIX}lmdb${LIB_
$shlib_directory/${LIB_PREFIX}mysql${LIB_SUFFIX}:f:root:-:755
$shlib_directory/${LIB_PREFIX}pcre${LIB_SUFFIX}:f:root:-:755
$shlib_directory/${LIB_PREFIX}pgsql${LIB_SUFFIX}:f:root:-:755
+$shlib_directory/${LIB_PREFIX}redis${LIB_SUFFIX}:f:root:-:755
$shlib_directory/${LIB_PREFIX}sdbm${LIB_SUFFIX}:f:root:-:755
$shlib_directory/${LIB_PREFIX}sqlite${LIB_SUFFIX}:f:root:-:755
$meta_directory/dynamicmaps.cf.d:d:root:-:755
@@ -200,6 +201,7 @@ $manpage_directory/man5/sqlite_table.5:f
$manpage_directory/man5/nisplus_table.5:f:root:-:644
$manpage_directory/man5/pcre_table.5:f:root:-:644
$manpage_directory/man5/pgsql_table.5:f:root:-:644
+$manpage_directory/man5/redis_table.5:f:root:-:644
$manpage_directory/man5/postconf.5:f:root:-:644
$manpage_directory/man5/postfix-wrapper.5:f:root:-:644
$manpage_directory/man5/regexp_table.5:f:root:-:644
@@ -307,6 +309,7 @@ $readme_directory/OVERVIEW:f:root:-:644
$readme_directory/PACKAGE_README:f:root:-:644
$readme_directory/PCRE_README:f:root:-:644
$readme_directory/PGSQL_README:f:root:-:644
+$readme_directory/REDIS_README:f:root:-:644
$readme_directory/POSTSCREEN_README:f:root:-:644
$readme_directory/QMQP_README:f:root:-:644:o
$readme_directory/QSHAPE_README:f:root:-:644
@@ -363,6 +366,7 @@ $html_directory/OVERVIEW.html:f:root:-:6
$html_directory/PACKAGE_README.html:f:root:-:644
$html_directory/PCRE_README.html:f:root:-:644
$html_directory/PGSQL_README.html:f:root:-:644
+$html_directory/REDIS_README.html:f:root:-:644
$html_directory/POSTSCREEN_README.html:f:root:-:644
$html_directory/QMQP_README.html:f:root:-:644:o
$html_directory/QSHAPE_README.html:f:root:-:644
@@ -414,6 +418,7 @@ $html_directory/newaliases.1.html:h:$htm
$html_directory/oqmgr.8.html:f:root:-:644
$html_directory/pcre_table.5.html:f:root:-:644
$html_directory/pgsql_table.5.html:f:root:-:644
+$html_directory/redis_table.5.html:f:root:-:644
$html_directory/pickup.8.html:f:root:-:644
$html_directory/pipe.8.html:f:root:-:644
$html_directory/postalias.1.html:f:root:-:644
diff -Nurp a/html/REDIS_README.html b/html/REDIS_README.html
--- a/makedefs 2020-09-20 22:25:37.000000000 +0100
+++ b/makedefs 2020-09-23 20:42:28.009667536 +0100
@@ -1178,7 +1178,7 @@ DEFINED_MAP_TYPES=`
# Propagate AUXLIBS_FOO or merge them into global AUXLIBS (i.e. SYSLIBS).
-PLUGGABLE_MAPS="CDB LDAP LMDB MYSQL PCRE PGSQL SDBM SQLITE"
+PLUGGABLE_MAPS="CDB LDAP LMDB MYSQL PCRE PGSQL REDIS SDBM SQLITE"
case "$dynamicmaps" in
yes) for name in $PLUGGABLE_MAPS
diff -Nurp a/man/Makefile.in b/man/Makefile.in
--- a/man/Makefile.in 2019-01-19 22:12:31.000000000 +0000
+++ b/man/Makefile.in 2020-09-23 21:01:00.416537285 +0100
@@ -17,7 +17,7 @@ CONFIG = man5/access.5 man5/aliases.5 ma
man5/transport.5 man5/virtual.5 man5/pcre_table.5 man5/regexp_table.5 \
man5/cidr_table.5 man5/tcp_table.5 man5/header_checks.5 \
man5/body_checks.5 man5/ldap_table.5 man5/lmdb_table.5 \
- man5/memcache_table.5 man5/mysql_table.5 \
+ man5/memcache_table.5 man5/mysql_table.5 man5/redis_table.5 \
man5/pgsql_table.5 man5/master.5 man5/nisplus_table.5 \
man5/generic.5 man5/bounce.5 man5/postfix-wrapper.5 \
man5/sqlite_table.5 man5/socketmap_table.5
@@ -345,6 +345,11 @@ man5/pgsql_table.5: ../proto/pgsql_table
../mantools/fixman ../proto/postconf.proto $? >junk && \
(cmp -s junk $? || mv junk $?) && rm -f junk
../mantools/srctoman - $? >$@
+
+man5/redis_table.5: ../proto/redis_table
+ ../mantools/fixman ../proto/postconf.proto $? >junk && \
+ (cmp -s junk $? || mv junk $?) && rm -f junk
+ ../mantools/srctoman - $? >$@
man5/regexp_table.5: ../proto/regexp_table
../mantools/fixman ../proto/postconf.proto $? >junk && \
diff -Nurp a/src/global/mail_dict.c b/src/global/mail_dict.c
--- a/src/global/mail_dict.c 2014-06-22 01:42:55.000000000 +0100
+++ b/src/global/mail_dict.c 2020-09-23 20:42:28.009667536 +0100
@@ -45,6 +45,7 @@
#include <dict_ldap.h>
#include <dict_mysql.h>
#include <dict_pgsql.h>
+#include <dict_redis.h>
#include <dict_sqlite.h>
#include <dict_memcache.h>
#include <mail_dict.h>
@@ -68,6 +69,9 @@ static const DICT_OPEN_INFO dict_open_in
#ifdef HAS_PGSQL
DICT_TYPE_PGSQL, dict_pgsql_open,
#endif
+#ifdef HAS_REDIS
+ DICT_TYPE_REDIS, dict_redis_open,
+#endif
#ifdef HAS_SQLITE
DICT_TYPE_SQLITE, dict_sqlite_open,
#endif
diff -Nurp a/src/global/Makefile.in b/src/global/Makefile.in
--- a/src/global/Makefile.in 2020-09-15 00:21:37.000000000 +0100
+++ b/src/global/Makefile.in 2020-09-23 20:42:28.013667515 +0100
@@ -3,7 +3,7 @@ SRCS = abounce.c anvil_clnt.c been_here.
canon_addr.c cfg_parser.c cleanup_strerror.c cleanup_strflags.c \
clnt_stream.c conv_time.c db_common.c debug_peer.c debug_process.c \
defer.c deliver_completed.c deliver_flock.c deliver_pass.c \
- deliver_request.c dict_ldap.c dict_mysql.c dict_pgsql.c \
+ deliver_request.c dict_ldap.c dict_mysql.c dict_pgsql.c dict_redis.c \
dict_proxy.c dict_sqlite.c domain_list.c dot_lockfile.c dot_lockfile_as.c \
dsb_scan.c dsn.c dsn_buf.c dsn_mask.c dsn_print.c dsn_util.c \
ehlo_mask.c ext_prop.c file_id.c flush_clnt.c header_opts.c \
@@ -78,13 +78,13 @@ OBJS = abounce.o anvil_clnt.o been_here.
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
# When hard-linking these maps, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
# otherwise it sets the PLUGIN_* macros.
-MAP_OBJ = dict_ldap.o dict_mysql.o dict_pgsql.o dict_sqlite.o mkmap_cdb.o \
+MAP_OBJ = dict_ldap.o dict_mysql.o dict_pgsql.o dict_redis.o dict_sqlite.o mkmap_cdb.o \
mkmap_lmdb.o mkmap_sdbm.o
HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \
conv_time.h db_common.h debug_peer.h debug_process.h defer.h \
deliver_completed.h deliver_flock.h deliver_pass.h deliver_request.h \
- dict_ldap.h dict_mysql.h dict_pgsql.h dict_proxy.h dict_sqlite.h domain_list.h \
+ dict_ldap.h dict_mysql.h dict_pgsql.h dict_redis.h dict_proxy.h dict_sqlite.h domain_list.h \
dot_lockfile.h dot_lockfile_as.h dsb_scan.h dsn.h dsn_buf.h \
dsn_mask.h dsn_print.h dsn_util.h ehlo_mask.h ext_prop.h \
file_id.h flush_clnt.h header_opts.h header_token.h input_transp.h \
@@ -131,7 +131,7 @@ LIBS = ../../lib/lib$(LIB_PREFIX)util$(L
LIB_DIR = ../../lib
INC_DIR = ../../include
PLUGIN_MAP_SO = $(LIB_PREFIX)ldap$(LIB_SUFFIX) $(LIB_PREFIX)mysql$(LIB_SUFFIX) \
- $(LIB_PREFIX)pgsql$(LIB_SUFFIX) $(LIB_PREFIX)sqlite$(LIB_SUFFIX) \
+ $(LIB_PREFIX)pgsql$(LIB_SUFFIX) $(LIB_PREFIX)redis$(LIB_SUFFIX) $(LIB_PREFIX)sqlite$(LIB_SUFFIX) \
$(LIB_PREFIX)lmdb$(LIB_SUFFIX) $(LIB_PREFIX)cdb$(LIB_SUFFIX) \
$(LIB_PREFIX)sdbm$(LIB_SUFFIX)
MAKES =
@@ -167,6 +167,9 @@ $(LIB_PREFIX)mysql$(LIB_SUFFIX): dict_my
$(LIB_PREFIX)pgsql$(LIB_SUFFIX): dict_pgsql.o
$(PLUGIN_LD) $(SHLIB_RPATH) -o $@ dict_pgsql.o $(AUXLIBS_PGSQL)
+$(LIB_PREFIX)redis$(LIB_SUFFIX): dict_redis.o
+ $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ dict_redis.o $(AUXLIBS_REDIS)
+
$(LIB_PREFIX)sqlite$(LIB_SUFFIX): dict_sqlite.o
$(PLUGIN_LD) $(SHLIB_RPATH) -o $@ dict_sqlite.o $(AUXLIBS_SQLITE)
@@ -521,6 +524,8 @@ surrogate_test: mail_dict surrogate.ref
echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict mysql:/xx read >>surrogate.tmp 2>&1
echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict pgsql:/xx write >>surrogate.tmp 2>&1
echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict pgsql:/xx read >>surrogate.tmp 2>&1
+ echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict redis:/xx write >>surrogate.tmp 2>&1
+ echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict redis:/xx read >>surrogate.tmp 2>&1
echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict sqlite:/xx write >>surrogate.tmp 2>&1
echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict sqlite:/xx read >>surrogate.tmp 2>&1
echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict memcache:/xx read >>surrogate.tmp 2>&1
@@ -1184,6 +1189,17 @@ dict_pgsql.o: db_common.h
dict_pgsql.o: dict_pgsql.c
dict_pgsql.o: dict_pgsql.h
dict_pgsql.o: string_list.h
+dict_redis.o: ../../include/dict.h
+dict_redis.o: ../../include/msg.h
+dict_redis.o: ../../include/mymalloc.h
+dict_redis.o: ../../include/vbuf.h
+dict_redis.o: ../../include/vstream.h
+dict_redis.o: ../../include/vstring.h
+dict_redis.o: ../../include/stringops.h
+dict_redis.o: ../../include/sys_defs.h
+dict_redis.o: cfg_parser.h
+dict_redis.o: dict_redis.c
+dict_redis.o: dict_redis.h
dict_proxy.o: ../../include/argv.h
dict_proxy.o: ../../include/attr.h
dict_proxy.o: ../../include/check_arg.h
@@ -1770,6 +1786,7 @@ mail_dict.o: dict_ldap.h
mail_dict.o: dict_memcache.h
mail_dict.o: dict_mysql.h
mail_dict.o: dict_pgsql.h
+mail_dict.o: dict_redis.h
mail_dict.o: dict_proxy.h
mail_dict.o: dict_sqlite.h
mail_dict.o: dynamicmaps.h
diff -Nurp a/html/REDIS_README.html b/html/REDIS_README.html
--- a/html/REDIS_README.html 1970-01-01 01:00:00.000000000 +0100
+++ b/html/REDIS_README.html 2021-02-27 08:47:15.302235467 +0000
@@ -0,0 +1,105 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+
+<head>
+
+<title>Postfix Redis Howto</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+
+</head>
+
+<body>
+
+<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix Redis Howto</h1>
+
+<hr>
+
+<h2>Introduction</h2>
+
+<p> The Postfix redis map type allows you to hook up Postfix to a
+Redis database. </p>
+
+<h2>Building Postfix with Redis support</h2>
+
+<p> These instructions assume that you build Postfix from source
+code as described in the <a href="INSTALL.html">INSTALL</a> document. Some modification may
+be required if you build Postfix from a vendor-specific source
+package. </p>
+
+<p> In order to build Postfix with redis map support, you specify
+-DHAS_REDIS, the directory with the hiredis header files, and
+the location of the hiredis library file. </p>
+
+<p> For example: </p>
+
+<blockquote>
+<pre>
+% make tidy
+% make -f Makefile.init makefiles \
+ 'CCARGS=-DHAS_REDIS $(pkg-config --cflags hiredis)' \
+ '<a href="REDIS_README.html">AUXLIBS_REDIS</a>=$(pkg-config --libs hiredis)'
+</pre>
+</blockquote>
+
+<blockquote>
+
+<p> Failure to use the <a href="REDIS_README.html">AUXLIBS_REDIS</a> variable will defeat the purpose
+of dynamic database client loading. Every Postfix executable file
+will have Redis database library dependencies. And that was exactly
+what dynamic database client loading was meant to avoid. </p>
+
+</blockquote>
+
+<p> Then just run 'make'. </p>
+
+<h2>Configuring Redis lookup tables</h2>
+
+<p> Once Postfix is built with redis support, you can specify a
+map type in <a href="postconf.5.html">main.cf</a> like this: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
+ <a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="redis_table.5.html">redis</a>:/etc/postfix/redis-aliases.cf
+</pre>
+</blockquote>
+
+<p> The file /etc/postfix/redis-aliases.cf specifies how to reach the redis database.
+For a complete description, see the <a href="redis_table.5.html">redis_table(5)</a> manual page. </p>
+
+<h2>Example: local aliases </h2>
+
+<pre>
+#
+# redis config file for <a href="virtual.8.html">virtual(8)</a> lookups
+#
+
+#
+# The hosts that Postfix will try to connect to
+host = 127.0.0.1
+
+# The prefix added to the query to check with redis
+prefix = VDOM:
+</pre>
+
+<h2>Using mirrored databases</h2>
+
+<p> Sites that have a need for multiple mail exchangers can setup a redis cluster
+if needed, for fallover capability. </p>
+
+<h2>Credits</h2>
+
+<ul>
+
+<li> This code is originaly by Titus T Jose.</li>
+
+<li> It has been updated by Duncan Bellamy.</li>
+
+</ul>
+
+</body>
+
+</html>
diff -Nurp a/man/man5/redis_table.5 b/man/man5/redis_table.5
--- a/man/man5/redis_table.5 1970-01-01 01:00:00.000000000 +0100
+++ b/man/man5/redis_table.5 2021-02-27 08:47:15.290235523 +0000
@@ -0,0 +1,108 @@
+.TH REDIS_TABLE 5
+.ad
+.fi
+.SH NAME
+redis_table
+\-
+Postfix Redis client configuration
+.SH "SYNOPSIS"
+.na
+.nf
+\fBpostmap \-q "\fIprefix:string\fB" redis:/etc/postfix/\fIfilename\fR
+
+\fBpostmap \-q \- redis:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
+.SH DESCRIPTION
+.ad
+.fi
+The Postfix mail system uses optional tables for address
+rewriting or mail routing. These tables are usually in
+\fBdbm\fR or \fBdb\fR format.
+
+Alternatively, lookup tables can be specified as Redis
+databases. In order to use Redis lookups, define a
+Redis source as a lookup table in main.cf, for example:
+.nf
+ virtual_alias_maps = redis:/etc/postfix/redis\-valias\-maps.cf
+.fi
+
+The file /etc/postfix/redis\-valias\-maps.cf has the same format as
+the Postfix main.cf file, and can specify the parameters
+described below.
+.SH "host"
+.na
+.nf
+.ad
+.fi
+The IP address of the host that Postfix will try to connect to and query
+from.
+
+Example:
+.nf
+ host = 127.0.0.1
+.fi
+
+.SH "port"
+.na
+.nf
+.ad
+.fi
+.IP "\fBport\fR"
+The port that Postfix will use trying to connect to and query
+from the Redis server. If not specified the default of \fB6379://\fR
+will be used.
+
+Example:
+.nf
+ port = 6379
+.fi
+
+.IP "\fBprefix\fR"
+This is the prefix that is added to the query from postfix before it is passed to
+redis for a lookup, allowing postfix to use simple key:value lookups from Redis.
+
+Examples:
+.nf
+ prefix = VALI
+ prefix = LOCAL
+ prefix = REV
+ prefix = HELO
+.fi
+
+.SH "SEE ALSO"
+.na
+.nf
+postmap(1), Postfix lookup table manager
+postconf(5), configuration parameters
+ldap_table(5), LDAP lookup tables
+mysql_table(5), MySQL lookup tables
+sqlite_table(5), SQLite lookup tables
+.SH "README FILES"
+.na
+.nf
+.ad
+.fi
+Use "\fBpostconf readme_directory\fR" or
+"\fBpostconf html_directory\fR" to locate this information.
+.na
+.nf
+DATABASE_README, Postfix lookup table overview
+REDIS_README
+.SH "LICENSE"
+.na
+.nf
+.ad
+.fi
+The Secure Mailer license must be distributed with this software.
+.SH HISTORY
+.ad
+.fi
+Redis support was introduced with Postfix version 3.?
+.SH "AUTHOR(S)"
+.na
+.nf
+Titus Jose
[email protected]
+
+Updated by:
+Duncan Bellamy
[email protected]
\ No newline at end of file
diff -Nurp a/README_FILES/REDIS_README b/README_FILES/REDIS_README
--- a/README_FILES/REDIS_README 1970-01-01 01:00:00.000000000 +0100
+++ b/README_FILES/REDIS_README 2021-02-27 08:47:15.294235504 +0000
@@ -0,0 +1,64 @@
+@@ -0,0 1,123 @@
+PPoossttffiixx PPoossttggrreeSSQQLL HHoowwttoo
+
+-------------------------------------------------------------------------------
+
+IInnttrroodduuccttiioonn
+
+The Postfix redis map type allows you to hook up Postfix to a Redis
+database.
+
+BBuuiillddiinngg PPoossttffiixx wwiitthh PPoossttggrreeSSQQLL ssuuppppoorrtt
+
+These instructions assume that you build Postfix from source code as described
+in the INSTALL document. Some modification may be required if you build Postfix
+from a vendor-specific source package.
+
+In order to build Postfix with redis map support, you specify -DHAS_REDIS, the
+directory with the hiredis header files, and the location of the hiredis
+library file.
+
+For example:
+
+ % make tidy
+ % make -f Makefile.init makefiles \
+ 'CCARGS=-DHAS_REDIS $(pkg-config --cflags hiredis)' \
+ 'AUXLIBS_REDIS=$(pkg-config --libs hiredis)'
+
+Then just run 'make'.
+
+CCoonnffiigguurriinngg PPoossttggrreeSSQQLL llooookkuupp ttaabblleess
+
+Once Postfix is built with redis support, you can specify a map type in main.cf
+like this:
+
+ /etc/postfix/main.cf:
+ virtual_mailbox_domains = redis:${config_directory}/redis-vdomains.cf
+
+The file ${config_directory}/redis-vdomains.cf specifies the information telling
+postfix how to connect to the redis database. It also has the prefix used to find
+the required key. For a complete description, see
+the redis_table(5) manual page.
+
+EExxaammppllee:: llooccaall aalliiaasseess
+
+#
+# redis config file for virtual(8) lookups
+#
+
+#
+# The hosts that Postfix will try to connect to
+host = 127.0.0.1
+
+# The prefix added to the query to check with redis
+prefix = VDOM:
+
+UUssiinngg mmiirrrroorreedd ddaattaabbaasseess
+
+Sites that have a need for multiple mail exchangers can setup a redis cluster
+if needed, for fallover capability.
+
+CCrreeddiittss
+
+ * This code is originaly by Titus T Jose.
+ * It has been updated by Duncan Bellamy.
diff -Nurp a/src/global/dict_redis.c b/src/global/dict_redis.c
--- a/src/global/dict_redis.c 1970-01-01 01:00:00.000000000 +0100
+++ b/src/global/dict_redis.c 2021-02-27 08:47:15.282235561 +0000
@@ -0,0 +1,217 @@
+/*++
+/* NAME
+/* dict_redis 3
+/* SUMMARY
+/* dictionary manager interface to Redis databases
+/* SYNOPSIS
+/* #include <dict_redis.h>
+/*
+/* DICT *dict_redis_open(name, open_flags, dict_flags)
+/* const char *name;
+/* int open_flags;
+/* int dict_flags;
+/* DESCRIPTION
+/* dict_redis_open() creates a dictionary of type 'redis'. This
+/* dictionary is an interface for the postfix key->value mappings
+/* to redis. The result is a pointer to the installed dictionary,
+/* or a null pointer in case of problems.
+/* .PP
+/* Arguments:
+/* .IP name
+/* Either the path to the Redis configuration file (if it
+/* starts with '/' or '.'), or the prefix which will be used to
+/* obtain main.cf configuration parameters for this search.
+/*
+/* In the first case, the configuration parameters below are
+/* specified in the file as \fIname\fR=\fIvalue\fR pairs.
+/*
+/* In the second case, the configuration parameters are
+/* prefixed with the value of \fIname\fR and an underscore,
+/* and they are specified in main.cf. For example, if this
+/* value is \fIredisDB\fR, the parameters would look like
+/* \fIredisDB_host\fR, \fIpredisDB_prefix\fR, and so on.
+/* .IP other_name
+/* reference for outside use.
+/* .IP open_flags
+/* unused.
+/* .IP dict_flags
+/* See dict_open(3).
+/*
+/* .PP
+/* Configuration parameters:
+/* .IP host
+/* IP address of the redis server hosting the database.
+/* .IP port
+/* Port number to connect to the above.
+/* .IP prefix
+/* Prefix to add to the key when looking it up.
+/* .PP
+/* For example, if you want the map to reference databases on
+/* redis host "127.0.0.1" and prefix the query with VDOM:
+/* Then the configuration file
+/* should read:
+/* .PP
+/* host = 127.0.0.1
+/* .br
+/* port = 6379
+/* .br
+/* prefix = VDOM:
+/* .PP
+/* SEE ALSO
+/* dict(3) generic dictionary manager
+/* AUTHOR(S)
+/* Titus Jose
+/* [email protected]
+/*
+/* Updated by:
+/* Duncan Bellamy
+/* [email protected]
+/*--*/
+
+#include "sys_defs.h"
+
+#ifdef HAS_REDIS
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
+
+/* Utility library. */
+
+#include "msg.h"
+#include "dict.h"
+#include "mymalloc.h"
+#include "vstring.h"
+#include "stringops.h"
+
+/* Global library. */
+
+#include "cfg_parser.h"
+
+/* Application-specific. */
+
+#include "dict_redis.h"
+#include "hiredis.h"
+
+typedef struct {
+ DICT dict;
+ CFG_PARSER *parser;
+ redisContext *c;
+ char *host;
+ int port;
+ char *prefix;
+} DICT_REDIS;
+
+/* internal function declarations */
+static const char *dict_redis_lookup(DICT *, const char *);
+DICT *dict_redis_open(const char *, int, int);
+static void dict_redis_close(DICT *);
+static void redis_parse_config(DICT_REDIS *, const char *);
+
+
+static const char *dict_redis_lookup(DICT *dict, const char *name)
+{
+ const char *myname = "dict_redis_lookup";
+ DICT_REDIS *dict_redis = (DICT_REDIS *) dict;
+ redisReply *reply;
+ const char *r;
+ VSTRING *result;
+ dict->error = 0;
+
+ result = vstring_alloc(10);
+ VSTRING_RESET(result);
+ VSTRING_TERMINATE(result);
+
+
+ if (msg_verbose)
+ msg_info("%s: Requesting key %s%s",dict_redis->host,dict_redis->prefix,name);
+ /*
+ * Optionally fold the key.
+ */
+ if (dict->flags & DICT_FLAG_FOLD_FIX) {
+ if (dict->fold_buf == 0)
+ dict->fold_buf = vstring_alloc(10);
+ vstring_strcpy(dict->fold_buf, name);
+ name = lowercase(vstring_str(dict->fold_buf));
+ }
+
+ if(dict_redis->c) {
+ reply = redisCommand(dict_redis->c,"GET %s%s",dict_redis->prefix,name);
+ }
+ else {
+ dict->error = DICT_ERR_CONFIG;
+ }
+ if(reply->str) {
+ vstring_strcpy(result,reply->str);
+ r = vstring_str(result);
+ freeReplyObject(reply);
+ }
+ else {
+ return(0);
+ }
+ return ((dict->error == 0 && *r) ? r : 0);
+}
+
+/* redis_parse_config - parse redis configuration file */
+
+static void redis_parse_config(DICT_REDIS *dict_redis, const char *rediscf)
+{
+ const char *myname = "redisname_parse";
+ CFG_PARSER *p = dict_redis->parser;
+
+ dict_redis->port = cfg_get_int(p, "port", 6379, 0, 0);
+ dict_redis->host = cfg_get_str(p, "host", "127.0.0.1", 1, 0);
+ dict_redis->prefix = cfg_get_str(p, "prefix", "", 0, 0);
+}
+
+/* dict_redis_open - open redis data base */
+
+DICT *dict_redis_open(const char *name, int open_flags, int dict_flags)
+{
+ DICT_REDIS *dict_redis;
+ CFG_PARSER *parser;
+ redisContext *c;
+
+ /*
+ * Open the configuration file.
+ */
+ if ((parser = cfg_parser_alloc(name)) == 0)
+ return (dict_surrogate(DICT_TYPE_REDIS, name, open_flags, dict_flags,
+ "open %s: %m", name));
+
+ dict_redis = (DICT_REDIS *) dict_alloc(DICT_TYPE_REDIS, name,
+ sizeof(DICT_REDIS));
+ dict_redis->dict.lookup = dict_redis_lookup;
+ dict_redis->dict.close = dict_redis_close;
+ dict_redis->dict.flags = dict_flags;
+ dict_redis->parser = parser;
+ redis_parse_config(dict_redis, name);
+ dict_redis->dict.owner = cfg_get_owner(dict_redis->parser);
+ c = redisConnect(dict_redis->host,dict_redis->port);
+ if(c->err) {
+ msg_fatal("%s:%s: Cannot connect to Redis server %s: %s\n",
+ DICT_TYPE_REDIS, name, dict_redis->host, c->errstr);
+ } else {
+ dict_redis->c = c;
+ }
+
+ return (DICT_DEBUG (&dict_redis->dict));
+}
+
+/* dict_redis_close - close redis database */
+
+static void dict_redis_close(DICT *dict)
+{
+ DICT_REDIS *dict_redis = (DICT_REDIS *) dict;
+
+ cfg_parser_free(dict_redis->parser);
+ myfree(dict_redis->host);
+ if (dict->fold_buf)
+ vstring_free(dict->fold_buf);
+ dict_free(dict);
+}
+
+#endif
diff -Nurp a/src/global/dict_redis.h b/src/global/dict_redis.h
--- a/src/global/dict_redis.h 1970-01-01 01:00:00.000000000 +0100
+++ b/src/global/dict_redis.h 2021-02-27 08:47:15.282235561 +0000
@@ -0,0 +1,10 @@
+#ifndef _DICT_REDIS_H_INCLUDED_
+#define _DICT_REDIS_H_INCLUDED_
+
+#include <dict.h>
+
+#define DICT_TYPE_REDIS "redis"
+
+extern DICT *dict_redis_open(const char *, int, int);
+
+#endif