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
+titus.n...@gmail.com
+
+Updated by:
+Duncan Bellamy
+d...@denkimushi.com
\ 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
+/*	titus.n...@gmail.com
+/*
+/*	Updated by:
+/*	Duncan Bellamy
+/*	d...@denkimushi.com
+/*--*/
+
+#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

Reply via email to