Hello,

I've created a patch that mimicked tcp_table. however, the table lookups are directed to a unix domain socket instead of tcp servers. Actually, the patch itself is a modification of the source code of tcp_table.

Map names have the form usock:/path/to/socket

If i'm not on the right path, can i request similiar feature.? (it would be great to have both tcp|unix-domain-socket_table) tcp_table is great, its simple protocol allows us to talk to various applications.

Thanks


Powered By http://www.3g-net.net
diff -Nur postfix-2.8.4.orig/src/util/dict_open.c 
postfix-2.8.4/src/util/dict_open.c
--- postfix-2.8.4.orig/src/util/dict_open.c     2011-04-12 00:37:49.000000000 
+0700
+++ postfix-2.8.4/src/util/dict_open.c  2011-07-30 17:44:16.486896139 +0700
@@ -199,6 +199,7 @@
 #include <dict_env.h>
 #include <dict_unix.h>
 #include <dict_tcp.h>
+#include <dict_usock.h>
 #include <dict_sdbm.h>
 #include <dict_dbm.h>
 #include <dict_db.h>
@@ -232,6 +233,7 @@
     DICT_TYPE_HT, dict_ht_open,
     DICT_TYPE_UNIX, dict_unix_open,
     DICT_TYPE_TCP, dict_tcp_open,
+    DICT_TYPE_USOCK, dict_usock_open,
 #ifdef HAS_SDBM
     DICT_TYPE_SDBM, dict_sdbm_open,
 #endif
diff -Nur postfix-2.8.4.orig/src/util/dict_usock.c 
postfix-2.8.4/src/util/dict_usock.c
--- postfix-2.8.4.orig/src/util/dict_usock.c    1970-01-01 07:00:00.000000000 
+0700
+++ postfix-2.8.4/src/util/dict_usock.c 2011-08-01 11:34:16.432844893 +0700
@@ -0,0 +1,315 @@
+/*++
+/* NAME
+/*     dict_usock 3
+/* SUMMARY
+/*     dictionary manager interface to unix-domain-socket-based lookup tables
+/* SYNOPSIS
+/*     #include <dict_usock.h>
+/*
+/*     DICT    *dict_usock_open(map, open_flags, dict_flags)
+/*     const char *map;
+/*     int     open_flags;
+/*     int     dict_flags;
+/* DESCRIPTION
+/*     dict_usock_open() makes a UNIX DOMAIN SOCKET server accessible via the 
generic
+/*     dictionary operations described in dict_open(3).
+/*     The only implemented operation is dictionary lookup. This map
+/*     type can be useful for simulating a dynamic lookup table.
+/*
+/*     Map names have the form usock:/path/to/socket.
+/*
+/*     The USOCK map class implements a very simple protocol: the client
+/*     sends a request, and the server sends one reply. Requests and
+/*     replies are sent as one line of ASCII text, terminated by the
+/*     ASCII newline character. Request and reply parameters (see below)
+/*     are separated by whitespace.
+/* ENCODING
+/* .ad
+/* .fi
+/*     In request and reply parameters, the character % and any non-printing
+/*     and whitespace characters must be replaced by %XX, XX being the
+/*     corresponding ASCII hexadecimal character value. The hexadecimal codes
+/*     can be specified in any case (upper, lower, mixed).
+/* REQUEST FORMAT
+/* .ad
+/* .fi
+/*     Requests are strings that serve as lookup key in the simulated
+/*     table.
+/* .IP "get SPACE key NEWLINE"
+/*     Look up data under the specified key.
+/* .IP "put SPACE key SPACE value NEWLINE"
+/*     This request is currently not implemented.
+/* REPLY FORMAT
+/* .ad
+/* .fi
+/*      Replies must be no longer than 4096 characters including the
+/*     newline terminator, and must have the following form:
+/* .IP "500 SPACE text NEWLINE"
+/*     In case of a lookup request, the requested data does not exist.
+/*     In case of an update request, the request was rejected.
+/*     The text gives the nature of the problem.
+/* .IP "400 SPACE text NEWLINE"
+/*     This indicates an error condition. The text gives the nature of
+/*     the problem. The client should retry the request later.
+/* .IP "200 SPACE text NEWLINE"
+/*     The request was successful. In the case of a lookup request,
+/*     the text contains an encoded version of the requested data.
+/* SECURITY
+/*     This map must not be used for security sensitive information,
+/*     because neither the connection nor the server are authenticated.
+/* SEE ALSO
+/*     dict(3) generic dictionary manager
+/*     hex_quote(3) http-style quoting
+/* DIAGNOSTICS
+/*     Fatal errors: out of memory, unknown host or service name,
+/*     attempt to update or iterate over map.
+/* BUGS
+/*     Only the lookup method is currently implemented.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include "sys_defs.h"
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <vstring.h>
+#include <vstream.h>
+#include <vstring_vstream.h>
+#include <connect.h>
+#include <hex_quote.h>
+#include <dict.h>
+#include <stringops.h>
+#include <dict_usock.h>
+
+/* Application-specific. */
+
+typedef struct {
+    DICT    dict;                      /* generic members */
+    VSTRING *raw_buf;                  /* raw I/O buffer */
+    VSTRING *hex_buf;                  /* quoted I/O buffer */
+    VSTREAM *fp;                       /* I/O stream */
+} DICT_USOCK;
+
+#define DICT_USOCK_MAXTRY      10              /* attempts before giving up */
+#define DICT_USOCK_TMOUT       100             /* connect/read/write timeout */
+#define DICT_USOCK_MAXLEN      4096            /* server reply size limit */
+
+#define STR(x)         vstring_str(x)
+
+/* dict_usock_connect - connect to UNIX DOMAIN SOCKET server */
+
+static int dict_usock_connect(DICT_USOCK *dict_usock)
+{
+    int     fd;
+
+    /*
+     * Connect to the server. Enforce a time limit on all operations so that
+     * we do not get stuck.
+     */
+    if ((fd = unix_connect(dict_usock->dict.name, NON_BLOCKING, 
DICT_USOCK_TMOUT)) < 0) {
+       msg_warn("connect to USOCK map %s: %m", dict_usock->dict.name);
+       return (-1);
+    }
+    dict_usock->fp = vstream_fdopen(fd, O_RDWR);
+    vstream_control(dict_usock->fp,
+                   VSTREAM_CTL_TIMEOUT, DICT_USOCK_TMOUT,
+                   VSTREAM_CTL_END);
+
+    /*
+     * Allocate per-map I/O buffers on the fly.
+     */
+    if (dict_usock->raw_buf == 0) {
+       dict_usock->raw_buf = vstring_alloc(10);
+       dict_usock->hex_buf = vstring_alloc(10);
+    }
+    return (0);
+}
+
+/* dict_usock_disconnect - disconnect from UNIX DOMAIN SOCKET server */
+
+static void dict_usock_disconnect(DICT_USOCK *dict_usock)
+{
+    (void) vstream_fclose(dict_usock->fp);
+    dict_usock->fp = 0;
+}
+
+/* dict_usock_lookup - request UNIX DOMAIN SOCKET server */
+
+static const char *dict_usock_lookup(DICT *dict, const char *key)
+{
+    DICT_USOCK *dict_usock = (DICT_USOCK *) dict;
+    const char *myname = "dict_usock_lookup";
+    int     tries;
+    char   *start;
+    int     last_ch;
+
+#define RETURN(errval, result) { dict_errno = errval; return (result); }
+
+    if (msg_verbose)
+       msg_info("%s: key %s", myname, key);
+
+    /*
+     * Optionally fold the key.
+     */
+    if (dict->flags & DICT_FLAG_FOLD_MUL) {
+       if (dict->fold_buf == 0)
+           dict->fold_buf = vstring_alloc(10);
+       vstring_strcpy(dict->fold_buf, key);
+       key = lowercase(vstring_str(dict->fold_buf));
+    }
+    for (tries = 0; /* see below */ ; /* see below */ ) {
+
+       /*
+        * Connect to the server, or use an existing connection.
+        */
+       if (dict_usock->fp != 0 || dict_usock_connect(dict_usock) == 0) {
+
+           /*
+            * Send request and receive response. Both are %XX quoted and
+            * both are terminated by newline. This encoding is convenient
+            * for data that is mostly text.
+            */
+           hex_quote(dict_usock->hex_buf, key);
+           vstream_fprintf(dict_usock->fp, "get %s\n", 
STR(dict_usock->hex_buf));
+           if (msg_verbose)
+               msg_info("%s: send: get %s", myname, STR(dict_usock->hex_buf));
+           last_ch = vstring_get_nonl_bound(dict_usock->hex_buf, 
dict_usock->fp,
+                                            DICT_USOCK_MAXLEN);
+           if (last_ch == '\n')
+               break;
+
+           /*
+            * Disconnect from the server if it can't talk to us.
+            */
+           if (last_ch < 0)
+               msg_warn("read USOCK map reply from %s: unexpected EOF (%m)",
+                        dict_usock->dict.name);
+           else
+               msg_warn("read USOCK map reply from %s: text longer than %d",
+                        dict_usock->dict.name, DICT_USOCK_MAXLEN);
+           dict_usock_disconnect(dict_usock);
+       }
+
+       /*
+        * Try to connect a limited number of times before giving up.
+        */
+       if (++tries >= DICT_USOCK_MAXTRY)
+           RETURN(DICT_ERR_RETRY, 0);
+
+       /*
+        * Sleep between attempts, instead of hammering the server.
+        */
+       sleep(1);
+    }
+    if (msg_verbose)
+       msg_info("%s: recv: %s", myname, STR(dict_usock->hex_buf));
+
+    /*
+     * Check the general reply syntax. If the reply is malformed, disconnect
+     * and try again later.
+     */
+    if (start = STR(dict_usock->hex_buf),
+       !ISDIGIT(start[0]) || !ISDIGIT(start[1])
+       || !ISDIGIT(start[2]) || !ISSPACE(start[3])
+       || !hex_unquote(dict_usock->raw_buf, start + 4)) {
+       msg_warn("read USOCK map reply from %s: malformed reply: %.100s",
+              dict_usock->dict.name, printable(STR(dict_usock->hex_buf), '_'));
+       dict_usock_disconnect(dict_usock);
+       RETURN(DICT_ERR_RETRY, 0);
+    }
+
+    /*
+     * Examine the reply status code. If the reply is malformed, disconnect
+     * and try again later.
+     */
+    switch (start[0]) {
+    default:
+       msg_warn("read USOCK map reply from %s: bad status code: %.100s",
+              dict_usock->dict.name, printable(STR(dict_usock->hex_buf), '_'));
+       dict_usock_disconnect(dict_usock);
+       RETURN(DICT_ERR_RETRY, 0);
+    case '4':
+       if (msg_verbose)
+           msg_info("%s: soft error: %s",
+                    myname, printable(STR(dict_usock->hex_buf), '_'));
+       dict_usock_disconnect(dict_usock);
+       RETURN(DICT_ERR_RETRY, 0);
+    case '5':
+       if (msg_verbose)
+           msg_info("%s: not found: %s",
+                    myname, printable(STR(dict_usock->hex_buf), '_'));
+       RETURN(DICT_ERR_NONE, 0);
+    case '2':
+       if (msg_verbose)
+           msg_info("%s: found: %s",
+                    myname, printable(STR(dict_usock->raw_buf), '_'));
+       RETURN(DICT_ERR_NONE, STR(dict_usock->raw_buf));
+    }
+}
+
+/* dict_usock_close - close USOCK map */
+
+static void dict_usock_close(DICT *dict)
+{
+    DICT_USOCK *dict_usock = (DICT_USOCK *) dict;
+
+    if (dict_usock->fp)
+       (void) vstream_fclose(dict_usock->fp);
+    if (dict_usock->raw_buf)
+       vstring_free(dict_usock->raw_buf);
+    if (dict_usock->hex_buf)
+       vstring_free(dict_usock->hex_buf);
+    if (dict->fold_buf)
+       vstring_free(dict->fold_buf);
+    dict_free(dict);
+}
+
+/* dict_usock_open - open USOCK map */
+
+DICT   *dict_usock_open(const char *map, int open_flags, int dict_flags)
+{
+    DICT_USOCK *dict_usock;
+
+    dict_errno = 0;
+
+    /*
+     * Sanity checks.
+     */
+    if (dict_flags & DICT_FLAG_NO_UNAUTH)
+       msg_fatal("%s:%s map is not allowed for security sensitive data",
+                 DICT_TYPE_USOCK, map);
+    if (open_flags != O_RDONLY)
+       msg_fatal("%s:%s map requires O_RDONLY access mode",
+                 DICT_TYPE_USOCK, map);
+
+    /*
+     * Create the dictionary handle. Do not open the connection until the
+     * first request is made.
+     */
+    dict_usock = (DICT_USOCK *) dict_alloc(DICT_TYPE_USOCK, map, 
sizeof(*dict_usock));
+    dict_usock->fp = 0;
+    dict_usock->raw_buf = dict_usock->hex_buf = 0;
+    dict_usock->dict.lookup = dict_usock_lookup;
+    dict_usock->dict.close = dict_usock_close;
+    dict_usock->dict.flags = dict_flags | DICT_FLAG_PATTERN;
+    if (dict_flags & DICT_FLAG_FOLD_MUL)
+       dict_usock->dict.fold_buf = vstring_alloc(10);
+
+    return (DICT_DEBUG (&dict_usock->dict));
+}
diff -Nur postfix-2.8.4.orig/src/util/dict_usock.h 
postfix-2.8.4/src/util/dict_usock.h
--- postfix-2.8.4.orig/src/util/dict_usock.h    1970-01-01 07:00:00.000000000 
+0700
+++ postfix-2.8.4/src/util/dict_usock.h 2011-08-01 11:34:00.052025049 +0700
@@ -0,0 +1,37 @@
+#ifndef _DICT_USOCK_H_INCLUDED_
+#define _DICT_USOCK_H_INCLUDED_
+
+/*++
+/* NAME
+/*     dict_usock 3h
+/* SUMMARY
+/*     dictionary manager interface to unix-domain-socket-based lookup tables
+/* SYNOPSIS
+/*     #include <dict_usock.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * Utility library.
+  */
+#include <dict.h>
+
+ /*
+  * External interface.
+  */
+#define DICT_TYPE_USOCK        "usock"
+
+extern DICT *dict_usock_open(const char *, int, int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
diff -Nur postfix-2.8.4.orig/src/util/Makefile.in 
postfix-2.8.4/src/util/Makefile.in
--- postfix-2.8.4.orig/src/util/Makefile.in     2011-04-15 23:52:47.000000000 
+0700
+++ postfix-2.8.4/src/util/Makefile.in  2011-07-30 17:44:16.489154827 +0700
@@ -6,7 +6,7 @@
        ctable.c dict.c dict_alloc.c dict_cdb.c dict_cidr.c dict_db.c \
        dict_dbm.c dict_debug.c dict_env.c dict_ht.c dict_ni.c dict_nis.c \
        dict_nisplus.c dict_open.c dict_pcre.c dict_regexp.c dict_sdbm.c \
-       dict_static.c dict_tcp.c dict_unix.c dir_forest.c doze.c dummy_read.c \
+       dict_static.c dict_tcp.c dict_usock.c dict_unix.c dir_forest.c doze.c 
dummy_read.c \
        dummy_write.c duplex_pipe.c environ.c events.c exec_command.c \
        fifo_listen.c fifo_trigger.c file_limit.c find_inet.c fsspace.c \
        fullname.c get_domainname.c get_hostname.c hex_code.c hex_quote.c \
@@ -41,7 +41,7 @@
        ctable.o dict.o dict_alloc.o dict_cdb.o dict_cidr.o dict_db.o \
        dict_dbm.o dict_debug.o dict_env.o dict_ht.o dict_ni.o dict_nis.o \
        dict_nisplus.o dict_open.o dict_pcre.o dict_regexp.o dict_sdbm.o \
-       dict_static.o dict_tcp.o dict_unix.o dir_forest.o doze.o dummy_read.o \
+       dict_static.o dict_tcp.o dict_usock.o dict_unix.o dir_forest.o doze.o 
dummy_read.o \
        dummy_write.o duplex_pipe.o environ.o events.o exec_command.o \
        fifo_listen.o fifo_trigger.o file_limit.o find_inet.o fsspace.o \
        fullname.o get_domainname.o get_hostname.o hex_code.o hex_quote.o \
@@ -73,7 +73,7 @@
        chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \
        dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \
        dict_ni.h dict_nis.h dict_nisplus.h dict_pcre.h dict_regexp.h \
-       dict_sdbm.h dict_static.h dict_tcp.h dict_unix.h dir_forest.h \
+       dict_sdbm.h dict_static.h dict_tcp.h dict_usock.h dict_unix.h 
dir_forest.h \
        events.h exec_command.h find_inet.h fsspace.h fullname.h \
        get_domainname.h get_hostname.h hex_code.h hex_quote.h host_port.h \
        htable.h inet_addr_host.h inet_addr_list.h inet_addr_local.h \
@@ -944,6 +944,7 @@
 dict_open.o: dict_sdbm.h
 dict_open.o: dict_static.h
 dict_open.o: dict_tcp.h
+dict_open.o: dict_usock.h
 dict_open.o: dict_thash.h
 dict_open.o: dict_unix.h
 dict_open.o: htable.h
@@ -1023,6 +1024,21 @@
 dict_tcp.o: vstream.h
 dict_tcp.o: vstring.h
 dict_tcp.o: vstring_vstream.h
+dict_usock.o: argv.h
+dict_usock.o: connect.h
+dict_usock.o: dict.h
+dict_usock.o: dict_usock.c
+dict_usock.o: dict_usock.h
+dict_usock.o: hex_quote.h
+dict_usock.o: iostuff.h
+dict_usock.o: msg.h
+dict_usock.o: mymalloc.h
+dict_usock.o: stringops.h
+dict_usock.o: sys_defs.h
+dict_usock.o: vbuf.h
+dict_usock.o: vstream.h
+dict_usock.o: vstring.h
+dict_usock.o: vstring_vstream.h
 dict_thash.o: argv.h
 dict_thash.o: dict.h
 dict_thash.o: dict_thash.c

Reply via email to