mirror of
https://git.freebsd.org/ports.git
synced 2025-06-20 12:10:31 -04:00
This will allow for easier integration with e.g. ports/mail/cyrus-imapd22, which already includes smmapd for realtime checking whether the mailbox exists and is not over quota. The patch adds 1) an extra knob in Makefile (WITH_SENDMAIL_SOCKETMAP). 3) the extra-patch-socketmap.patch is actually http://www.sendmail.org/~ca/email/patches/sendmail-8.12.7-socketmap-v4.patch slightly hacked (the pathnames) so it cleanly applies through ports(7). PR: 64566 Submitted by: Michael O. Boev - change PKGNAMESUFFIX - merge 1-line site.config.m4.* files into Makefile - update CONFLICTS
798 lines
23 KiB
Diff
798 lines
23 KiB
Diff
Index: sendmail/sendmail/sendmail/README
|
|
diff -u sendmail/sendmail/sendmail/README:1.1.1.2 sendmail/sendmail/sendmail/README:1.3
|
|
--- sendmail/README Thu Jan 23 11:50:26 2003
|
|
+++ sendmail/README Tue Jan 28 16:55:41 2003
|
|
@@ -127,6 +127,8 @@
|
|
PH_MAP PH map support. You will need the libphclient library from
|
|
the nph package (http://www-dev.cso.uiuc.edu/ph/nph/).
|
|
MAP_NSD nsd map support (IRIX 6.5 and later).
|
|
+SOCKETMAP Support for a trivial query protocol over UNIX domain or TCP
|
|
+ sockets.
|
|
|
|
>>> NOTE WELL for NEWDB support: If you want to get ndbm support, for
|
|
>>> Berkeley DB versions under 2.0, it is CRITICAL that you remove
|
|
@@ -180,6 +182,50 @@
|
|
check_* rule-set, you can block a certain range of addresses that would
|
|
otherwise be considered valid.
|
|
|
|
+The socket map uses a simple request/reply protocol over TCP or UNIX domain
|
|
+sockets to query an external server. Both requests and replies are text
|
|
+based and encoded as D.J. Bernsteins netstrings. E.g., a string
|
|
+"hello there" becomes:
|
|
+11:hello there,
|
|
+
|
|
+NB. neither requests nor replies end with CRLF.
|
|
+
|
|
+The request consists of the database map name and the lookup key separated
|
|
+by a space character:
|
|
+
|
|
+<mapname> ' ' <key>
|
|
+
|
|
+The server responds with a status indicator and the result (if any):
|
|
+
|
|
+<status> ' ' <result> <LF>
|
|
+
|
|
+The status indicator is one of the following upper case words:
|
|
+OK (the key was found, result contains the looked up value)
|
|
+NOTFOUND (the key was not found, the result is empty)
|
|
+TEMP (a temporary failure occured)
|
|
+TIMEOUT (a timeout occured on the server side)
|
|
+PERM (a permanent failure occured)
|
|
+
|
|
+In case of errors (status TEMP, TIMEOUT or PERM) the result fied may
|
|
+contain an explanatory message.
|
|
+
|
|
+Example replies:
|
|
+30:OK resolved.addess@example.com,
|
|
+
|
|
+in case of a successful lookup, or:
|
|
+7:NOTFOUND,
|
|
+
|
|
+in case the key was not found, or:
|
|
+54:TEMP this text explains that we had a temporary failure,
|
|
+
|
|
+in case of a failure.
|
|
+
|
|
+The socket map uses the same syntax as milters the specify the remote
|
|
+endpoint. E.g.:
|
|
+Ksocket mySocketMap inet:12345@127.0.0.1
|
|
+
|
|
+If multiple socket maps define the same remote endpoint, they will share
|
|
+a single connection to this endpoint.
|
|
|
|
+---------------+
|
|
| COMPILE FLAGS |
|
|
Index: sendmail/sendmail/sendmail/conf.c
|
|
diff -u sendmail/sendmail/sendmail/conf.c:1.1.1.2 sendmail/sendmail/sendmail/conf.c:1.6
|
|
--- sendmail/conf.c Thu Jan 23 11:50:27 2003
|
|
+++ sendmail/conf.c Fri Jan 24 15:31:59 2003
|
|
@@ -622,6 +622,13 @@
|
|
dequote_init, null_map_open, null_map_close,
|
|
arith_map_lookup, null_map_store);
|
|
|
|
+#if SOCKETMAP
|
|
+ /* arbitrary daemons */
|
|
+ MAPDEF("socket", NULL, MCF_ALIASOK,
|
|
+ map_parseargs, socket_map_open, socket_map_close,
|
|
+ socket_map_lookup, null_map_store);
|
|
+#endif /* SOCKETMAP */
|
|
+
|
|
if (tTd(38, 2))
|
|
{
|
|
/* bogus map -- always return tempfail */
|
|
Index: sendmail/sendmail/sendmail/map.c
|
|
diff -u sendmail/sendmail/sendmail/map.c:1.1.1.2 sendmail/sendmail/sendmail/map.c:1.25
|
|
--- sendmail/map.c Thu Jan 23 11:50:27 2003
|
|
+++ sendmail/map.c Tue Feb 25 14:57:14 2003
|
|
@@ -66,6 +66,9 @@
|
|
static bool ni_getcanonname __P((char *, int, int *));
|
|
#endif /* NETINFO */
|
|
static bool text_getcanonname __P((char *, int, int *));
|
|
+#ifdef SOCKETMAP
|
|
+static STAB * socket_map_findconn __P((const char*));
|
|
+#endif /* SOCKETMAP */
|
|
|
|
/* default error message for trying to open a map in write mode */
|
|
#ifdef ENOSYS
|
|
@@ -7395,3 +7398,646 @@
|
|
*statp = EX_CONFIG;
|
|
return NULL;
|
|
}
|
|
+
|
|
+#ifdef SOCKETMAP
|
|
+
|
|
+# if NETINET || NETINET6
|
|
+# include <arpa/inet.h>
|
|
+# endif /* NETINET || NETINET6 */
|
|
+
|
|
+#define socket_map_next map_stack[0]
|
|
+#define socket_map_previous map_stack[1]
|
|
+
|
|
+/*
|
|
+** SOCKET_MAP_OPEN -- open socket table
|
|
+*/
|
|
+
|
|
+bool
|
|
+socket_map_open(map, mode)
|
|
+ MAP *map;
|
|
+ int mode;
|
|
+{
|
|
+ STAB *s;
|
|
+
|
|
+ int sock = 0;
|
|
+ SOCKADDR_LEN_T addrlen = 0;
|
|
+ int addrno = 0;
|
|
+ int save_errno;
|
|
+ char *p;
|
|
+ char *colon;
|
|
+ char *at;
|
|
+ struct hostent *hp = NULL;
|
|
+ SOCKADDR addr;
|
|
+
|
|
+ if (tTd(38, 2))
|
|
+ sm_dprintf("socket_map_open(%s, %s, %d)\n",
|
|
+ map->map_mname, map->map_file, mode);
|
|
+
|
|
+ mode &= O_ACCMODE;
|
|
+
|
|
+ /* sendmail doesn't have the ability to write to SOCKET (yet) */
|
|
+ if (mode != O_RDONLY)
|
|
+ {
|
|
+ /* issue a pseudo-error message */
|
|
+ errno = SM_EMAPCANTWRITE;
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (*map->map_file == '\0')
|
|
+ {
|
|
+ syserr("socket map \"%s\": empty or missing socket information",
|
|
+ map->map_mname);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ s = socket_map_findconn(map->map_file);
|
|
+ if (s->s_socketmap != NULL)
|
|
+ {
|
|
+ /* Copy open connection */
|
|
+ map->map_db1 = s->s_socketmap->map_db1;
|
|
+
|
|
+ /* Add this map as head of linked list */
|
|
+ map->socket_map_next = s->s_socketmap;
|
|
+ s->s_socketmap = map;
|
|
+
|
|
+ if (tTd(38, 2))
|
|
+ sm_dprintf("using cached connection\n");
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ if (tTd(38, 2))
|
|
+ sm_dprintf("opening new connection\n");
|
|
+
|
|
+
|
|
+
|
|
+ /* following code is ripped from milter.c */
|
|
+
|
|
+ /* protocol:filename or protocol:port@host */
|
|
+ memset(&addr, '\0', sizeof addr);
|
|
+ p = map->map_file;
|
|
+ colon = strchr(p, ':');
|
|
+ if (colon != NULL)
|
|
+ {
|
|
+ *colon = '\0';
|
|
+
|
|
+ if (*p == '\0')
|
|
+ {
|
|
+# if NETUNIX
|
|
+ /* default to AF_UNIX */
|
|
+ addr.sa.sa_family = AF_UNIX;
|
|
+# else /* NETUNIX */
|
|
+# if NETINET
|
|
+ /* default to AF_INET */
|
|
+ addr.sa.sa_family = AF_INET;
|
|
+# else /* NETINET */
|
|
+# if NETINET6
|
|
+ /* default to AF_INET6 */
|
|
+ addr.sa.sa_family = AF_INET6;
|
|
+# else /* NETINET6 */
|
|
+ /* no protocols available */
|
|
+ syserr("socket map \"%s\": no valid socket protocols available",
|
|
+ map->map_mname);
|
|
+ return false;
|
|
+# endif /* NETINET6 */
|
|
+# endif /* NETINET */
|
|
+# endif /* NETUNIX */
|
|
+ }
|
|
+# if NETUNIX
|
|
+ else if (sm_strcasecmp(p, "unix") == 0 ||
|
|
+ sm_strcasecmp(p, "local") == 0)
|
|
+ addr.sa.sa_family = AF_UNIX;
|
|
+# endif /* NETUNIX */
|
|
+# if NETINET
|
|
+ else if (sm_strcasecmp(p, "inet") == 0)
|
|
+ addr.sa.sa_family = AF_INET;
|
|
+# endif /* NETINET */
|
|
+# if NETINET6
|
|
+ else if (sm_strcasecmp(p, "inet6") == 0)
|
|
+ addr.sa.sa_family = AF_INET6;
|
|
+# endif /* NETINET6 */
|
|
+ else
|
|
+ {
|
|
+# ifdef EPROTONOSUPPORT
|
|
+ errno = EPROTONOSUPPORT;
|
|
+# else /* EPROTONOSUPPORT */
|
|
+ errno = EINVAL;
|
|
+# endif /* EPROTONOSUPPORT */
|
|
+ syserr("socket map \"%s\": unknown socket type %s",
|
|
+ map->map_mname, p);
|
|
+ return false;
|
|
+ }
|
|
+ *colon++ = ':';
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ /* default to AF_UNIX */
|
|
+ addr.sa.sa_family = AF_UNIX;
|
|
+ colon = p;
|
|
+ }
|
|
+
|
|
+# if NETUNIX
|
|
+ if (addr.sa.sa_family == AF_UNIX)
|
|
+ {
|
|
+ long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK;
|
|
+
|
|
+ at = colon;
|
|
+ if (strlen(colon) >= sizeof addr.sunix.sun_path)
|
|
+ {
|
|
+ syserr("socket map \"%s\": local socket name %s too long",
|
|
+ map->map_mname, colon);
|
|
+ return false;
|
|
+ }
|
|
+ errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff,
|
|
+ S_IRUSR|S_IWUSR, NULL);
|
|
+
|
|
+ if (errno != 0)
|
|
+ {
|
|
+ /* if not safe, don't create */
|
|
+ syserr("socket map \"%s\": local socket name %s unsafe",
|
|
+ map->map_mname, colon);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ (void) sm_strlcpy(addr.sunix.sun_path, colon,
|
|
+ sizeof addr.sunix.sun_path);
|
|
+ addrlen = sizeof (struct sockaddr_un);
|
|
+ }
|
|
+ else
|
|
+# endif /* NETUNIX */
|
|
+# if NETINET || NETINET6
|
|
+ if (false
|
|
+# if NETINET
|
|
+ || addr.sa.sa_family == AF_INET
|
|
+# endif /* NETINET */
|
|
+# if NETINET6
|
|
+ || addr.sa.sa_family == AF_INET6
|
|
+# endif /* NETINET6 */
|
|
+ )
|
|
+ {
|
|
+ unsigned short port;
|
|
+
|
|
+ /* Parse port@host */
|
|
+ at = strchr(colon, '@');
|
|
+ if (at == NULL)
|
|
+ {
|
|
+ syserr("socket map \"%s\": bad address %s (expected port@host)",
|
|
+ map->map_mname, colon);
|
|
+ return false;
|
|
+ }
|
|
+ *at = '\0';
|
|
+ if (isascii(*colon) && isdigit(*colon))
|
|
+ port = htons((unsigned short) atoi(colon));
|
|
+ else
|
|
+ {
|
|
+# ifdef NO_GETSERVBYNAME
|
|
+ syserr("socket map \"%s\": invalid port number %s",
|
|
+ map->map_mname, colon);
|
|
+ return false;
|
|
+# else /* NO_GETSERVBYNAME */
|
|
+ register struct servent *sp;
|
|
+
|
|
+ sp = getservbyname(colon, "tcp");
|
|
+ if (sp == NULL)
|
|
+ {
|
|
+ syserr("socket map \"%s\": unknown port name %s",
|
|
+ map->map_mname, colon);
|
|
+ return false;
|
|
+ }
|
|
+ port = sp->s_port;
|
|
+# endif /* NO_GETSERVBYNAME */
|
|
+ }
|
|
+ *at++ = '@';
|
|
+ if (*at == '[')
|
|
+ {
|
|
+ char *end;
|
|
+
|
|
+ end = strchr(at, ']');
|
|
+ if (end != NULL)
|
|
+ {
|
|
+ bool found = false;
|
|
+# if NETINET
|
|
+ unsigned long hid = INADDR_NONE;
|
|
+# endif /* NETINET */
|
|
+# if NETINET6
|
|
+ struct sockaddr_in6 hid6;
|
|
+# endif /* NETINET6 */
|
|
+
|
|
+ *end = '\0';
|
|
+# if NETINET
|
|
+ if (addr.sa.sa_family == AF_INET &&
|
|
+ (hid = inet_addr(&at[1])) != INADDR_NONE)
|
|
+ {
|
|
+ addr.sin.sin_addr.s_addr = hid;
|
|
+ addr.sin.sin_port = port;
|
|
+ found = true;
|
|
+ }
|
|
+# endif /* NETINET */
|
|
+# if NETINET6
|
|
+ (void) memset(&hid6, '\0', sizeof hid6);
|
|
+ if (addr.sa.sa_family == AF_INET6 &&
|
|
+ anynet_pton(AF_INET6, &at[1],
|
|
+ &hid6.sin6_addr) == 1)
|
|
+ {
|
|
+ addr.sin6.sin6_addr = hid6.sin6_addr;
|
|
+ addr.sin6.sin6_port = port;
|
|
+ found = true;
|
|
+ }
|
|
+# endif /* NETINET6 */
|
|
+ *end = ']';
|
|
+ if (!found)
|
|
+ {
|
|
+ syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"",
|
|
+ map->map_mname, at);
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"",
|
|
+ map->map_mname, at);
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ hp = sm_gethostbyname(at, addr.sa.sa_family);
|
|
+ if (hp == NULL)
|
|
+ {
|
|
+ syserr("socket map \"%s\": Unknown host name %s",
|
|
+ map->map_mname, at);
|
|
+ return false;
|
|
+ }
|
|
+ addr.sa.sa_family = hp->h_addrtype;
|
|
+ switch (hp->h_addrtype)
|
|
+ {
|
|
+# if NETINET
|
|
+ case AF_INET:
|
|
+ memmove(&addr.sin.sin_addr,
|
|
+ hp->h_addr, INADDRSZ);
|
|
+ addr.sin.sin_port = port;
|
|
+ addrlen = sizeof (struct sockaddr_in);
|
|
+ addrno = 1;
|
|
+ break;
|
|
+# endif /* NETINET */
|
|
+
|
|
+# if NETINET6
|
|
+ case AF_INET6:
|
|
+ memmove(&addr.sin6.sin6_addr,
|
|
+ hp->h_addr, IN6ADDRSZ);
|
|
+ addr.sin6.sin6_port = port;
|
|
+ addrlen = sizeof (struct sockaddr_in6);
|
|
+ addrno = 1;
|
|
+ break;
|
|
+# endif /* NETINET6 */
|
|
+
|
|
+ default:
|
|
+ syserr("socket map \"%s\": Unknown protocol for %s (%d)",
|
|
+ map->map_mname, at, hp->h_addrtype);
|
|
+# if NETINET6
|
|
+ freehostent(hp);
|
|
+# endif /* NETINET6 */
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+# endif /* NETINET || NETINET6 */
|
|
+ {
|
|
+ syserr("socket map \"%s\": unknown socket protocol", map->map_mname);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /* nope, actually connecting */
|
|
+ for (;;)
|
|
+ {
|
|
+ sock = socket(addr.sa.sa_family, SOCK_STREAM, 0);
|
|
+ if (sock < 0)
|
|
+ {
|
|
+ save_errno = errno;
|
|
+ if (tTd(38, 5))
|
|
+ sm_dprintf("socket map \"%s\": error creating socket: %s\n",
|
|
+ map->map_mname,
|
|
+ sm_errstring(save_errno));
|
|
+# if NETINET6
|
|
+ if (hp != NULL)
|
|
+ freehostent(hp);
|
|
+# endif /* NETINET6 */
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (connect(sock, (struct sockaddr *) &addr, addrlen) >= 0)
|
|
+ break;
|
|
+
|
|
+ /* couldn't connect.... try next address */
|
|
+ save_errno = errno;
|
|
+ p = CurHostName;
|
|
+ CurHostName = at;
|
|
+ if (tTd(38, 5))
|
|
+ sm_dprintf("socket_open (%s): open %s failed: %s\n",
|
|
+ map->map_mname, at, sm_errstring(save_errno));
|
|
+ CurHostName = p;
|
|
+ (void) close(sock);
|
|
+
|
|
+ /* try next address */
|
|
+ if (hp != NULL && hp->h_addr_list[addrno] != NULL)
|
|
+ {
|
|
+ switch (addr.sa.sa_family)
|
|
+ {
|
|
+# if NETINET
|
|
+ case AF_INET:
|
|
+ memmove(&addr.sin.sin_addr,
|
|
+ hp->h_addr_list[addrno++],
|
|
+ INADDRSZ);
|
|
+ break;
|
|
+# endif /* NETINET */
|
|
+
|
|
+# if NETINET6
|
|
+ case AF_INET6:
|
|
+ memmove(&addr.sin6.sin6_addr,
|
|
+ hp->h_addr_list[addrno++],
|
|
+ IN6ADDRSZ);
|
|
+ break;
|
|
+# endif /* NETINET6 */
|
|
+
|
|
+ default:
|
|
+ if (tTd(38, 5))
|
|
+ sm_dprintf("socket map \"%s\": Unknown protocol for %s (%d)\n",
|
|
+ map->map_mname, at,
|
|
+ hp->h_addrtype);
|
|
+# if NETINET6
|
|
+ freehostent(hp);
|
|
+# endif /* NETINET6 */
|
|
+ return false;
|
|
+ }
|
|
+ continue;
|
|
+ }
|
|
+ p = CurHostName;
|
|
+ CurHostName = at;
|
|
+ if (tTd(38, 5))
|
|
+ sm_dprintf("socket map \"%s\": error connecting to socket map: %s\n",
|
|
+ map->map_mname, sm_errstring(save_errno));
|
|
+ CurHostName = p;
|
|
+# if NETINET6
|
|
+ if (hp != NULL)
|
|
+ freehostent(hp);
|
|
+# endif /* NETINET6 */
|
|
+ return false;
|
|
+ }
|
|
+# if NETINET6
|
|
+ if (hp != NULL)
|
|
+ {
|
|
+ freehostent(hp);
|
|
+ hp = NULL;
|
|
+ }
|
|
+# endif /* NETINET6 */
|
|
+ if ((map->map_db1 = (ARBPTR_T) sm_io_open(SmFtStdiofd,
|
|
+ SM_TIME_DEFAULT,
|
|
+ (void *) &sock,
|
|
+ SM_IO_RDWR,
|
|
+ NULL)) == NULL)
|
|
+ {
|
|
+ close(sock);
|
|
+ if (tTd(38, 2))
|
|
+ sm_dprintf("socket_open (%s): failed to create stream: %s\n",
|
|
+ map->map_mname, sm_errstring(errno));
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /* Save connection for reuse */
|
|
+ s->s_socketmap = map;
|
|
+ return true;
|
|
+}
|
|
+
|
|
+/*
|
|
+** SOCKET_MAP_FINDCONN -- find a SOCKET connection to the server
|
|
+**
|
|
+** Cache SOCKET connections based on the connection specifier
|
|
+** and PID so we don't have multiple connections open to
|
|
+** the same server for different maps. Need a separate connection
|
|
+** per PID since a parent process may close the map before the
|
|
+** child is done with it.
|
|
+**
|
|
+** Parameters:
|
|
+** conn -- SOCKET map connection specifier
|
|
+**
|
|
+** Returns:
|
|
+** Symbol table entry for the SOCKET connection.
|
|
+*/
|
|
+
|
|
+static STAB *
|
|
+socket_map_findconn(conn)
|
|
+ const char *conn;
|
|
+{
|
|
+ char *format;
|
|
+ char *nbuf;
|
|
+ STAB *SM_NONVOLATILE s = NULL;
|
|
+
|
|
+ format = "%s%c%d";
|
|
+ nbuf = sm_stringf_x(format,
|
|
+ conn,
|
|
+ CONDELSE,
|
|
+ (int) CurrentPid);
|
|
+ if (tTd(38, 20))
|
|
+ sm_dprintf("socket_find_conn '%s'\n", nbuf);
|
|
+ SM_TRY
|
|
+ s = stab(nbuf, ST_SOCKETMAP, ST_ENTER);
|
|
+ SM_FINALLY
|
|
+ sm_free(nbuf);
|
|
+ SM_END_TRY
|
|
+ return s;
|
|
+}
|
|
+
|
|
+/*
|
|
+** SOCKET_MAP_CLOSE -- close the socket
|
|
+*/
|
|
+
|
|
+void
|
|
+socket_map_close(map)
|
|
+ MAP *map;
|
|
+{
|
|
+ STAB *s;
|
|
+ MAP *smap;
|
|
+
|
|
+ if (tTd(38, 20))
|
|
+ sm_dprintf("socket_map_close(%s), pid=%d\n", map->map_file,(int) CurrentPid);
|
|
+
|
|
+ /* Check if already closed */
|
|
+ if (!map->map_db1)
|
|
+ {
|
|
+ if (tTd(38, 20))
|
|
+ sm_dprintf("socket_map_close(%s) already closed\n", map->map_file);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ sm_io_close((SM_FILE_T *)map->map_db1, SM_TIME_DEFAULT);
|
|
+
|
|
+ /* Mark all the maps that share the connection as closed */
|
|
+ s = socket_map_findconn(map->map_file);
|
|
+
|
|
+ smap = s->s_socketmap;
|
|
+
|
|
+ while (smap != NULL)
|
|
+ {
|
|
+ MAP *next;
|
|
+
|
|
+ if (tTd(38, 2) && smap != map)
|
|
+ sm_dprintf("socket_map_close(%s): closed %s (shared SOCKET connection)\n",
|
|
+ map->map_mname, smap->map_mname);
|
|
+
|
|
+ smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
|
|
+ smap->map_db1 = NULL;
|
|
+ next = smap->socket_map_next;
|
|
+ smap->socket_map_next = NULL;
|
|
+ smap = next;
|
|
+ }
|
|
+
|
|
+ s->s_socketmap = NULL;
|
|
+}
|
|
+
|
|
+/*
|
|
+** SOCKET_MAP_LOOKUP -- look up a datum in a SOCKET table
|
|
+*/
|
|
+
|
|
+char *
|
|
+socket_map_lookup(map, name, av, statp)
|
|
+ MAP *map;
|
|
+ char *name;
|
|
+ char **av;
|
|
+ int *statp;
|
|
+{
|
|
+ size_t nettolen;
|
|
+ char *rval = NULL;
|
|
+ SM_FILE_T *f = (SM_FILE_T *)map->map_db1;
|
|
+
|
|
+ if (tTd(38, 20))
|
|
+ sm_dprintf("socket_map_lookup(%s, %s) %s\n",
|
|
+ map->map_mname, name, map->map_file);
|
|
+
|
|
+ nettolen = strlen(map->map_mname) + 1 + strlen(name);
|
|
+ if ((sm_io_fprintf(f, SM_TIME_DEFAULT, "%u:%s %s,",
|
|
+ nettolen, map->map_mname, name) == SM_IO_EOF) || (sm_io_flush(f, SM_TIME_DEFAULT) != 0) ||
|
|
+ (sm_io_error(f)))
|
|
+ {
|
|
+ syserr("socket_map_lookup(%s): failed to send lookup request",
|
|
+ map->map_mname);
|
|
+ *statp = EX_TEMPFAIL;
|
|
+ socket_map_close(map);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ size_t replylen;
|
|
+
|
|
+ if (sm_io_fscanf(f, SM_TIME_DEFAULT, "%9u", &replylen) != 1)
|
|
+ {
|
|
+ syserr("socket_map_lookup(%s): failed to read length parameter of reply",
|
|
+ map->map_mname);
|
|
+ *statp = EX_TEMPFAIL;
|
|
+ socket_map_close(map);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ /* XXX arbitrary limit for sanity */
|
|
+ if (replylen > 1000000)
|
|
+ {
|
|
+ syserr("socket_map_lookup(%s): reply too long: %u",
|
|
+ map->map_mname, replylen);
|
|
+ /* *statp = EX_PROTOCOL; */
|
|
+ *statp = EX_TEMPFAIL;
|
|
+ socket_map_close(map);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (sm_io_getc(f, SM_TIME_DEFAULT) != ':')
|
|
+ {
|
|
+ syserr("socket_map_lookup(%s): missing ':' in reply",
|
|
+ map->map_mname);
|
|
+ /* *statp = EX_PROTOCOL; */
|
|
+ *statp = EX_TEMPFAIL;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ size_t recvlen;
|
|
+ char *replybuf = (char *) sm_malloc(replylen + 1);
|
|
+ recvlen = sm_io_read(f, SM_TIME_DEFAULT,
|
|
+ replybuf, replylen);
|
|
+ if (recvlen < replylen)
|
|
+ {
|
|
+ syserr("socket_map_lookup(%s): received only %u of %u reply characters",
|
|
+ map->map_mname, recvlen, replylen);
|
|
+ *statp = EX_TEMPFAIL;
|
|
+ socket_map_close(map);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (sm_io_getc(f, SM_TIME_DEFAULT) != ',')
|
|
+ {
|
|
+ syserr("socket_map_lookup(%s): missing ',' in reply",
|
|
+ map->map_mname);
|
|
+ /* *statp = EX_PROTOCOL; */
|
|
+ *statp = EX_TEMPFAIL;
|
|
+ socket_map_close(map);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ char *value;
|
|
+ char *status = replybuf;
|
|
+
|
|
+ replybuf[recvlen] = '\0';
|
|
+ value = strchr(replybuf, ' ');
|
|
+ if (value != NULL)
|
|
+ {
|
|
+ *value = '\0';
|
|
+ value++;
|
|
+ }
|
|
+
|
|
+ if (strcmp(status, "OK") == 0)
|
|
+ {
|
|
+ *statp = EX_OK;
|
|
+
|
|
+ /* collect the return value */
|
|
+ if (bitset(MF_MATCHONLY, map->map_mflags))
|
|
+ rval = map_rewrite(map, name, strlen(name), NULL);
|
|
+ else
|
|
+ rval = map_rewrite(map, value, strlen(value), av);
|
|
+ }
|
|
+ else if(strcmp(status, "NOTFOUND") == 0)
|
|
+ {
|
|
+ *statp = EX_NOTFOUND;
|
|
+ if (tTd(38, 20))
|
|
+ sm_dprintf("socket_map_lookup(%s): %s not found\n",
|
|
+ map->map_mname, name);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (tTd(38, 5))
|
|
+ sm_dprintf("socket_map_lookup(%s, %s): server returned error: type=%s, reason=%s\n",
|
|
+ map->map_mname, name, status,
|
|
+ value ? value : "");
|
|
+ if ((strcmp(status, "TEMP") == 0) ||
|
|
+ (strcmp(status, "TIMEOUT") == 0))
|
|
+ {
|
|
+ *statp = EX_TEMPFAIL;
|
|
+ }
|
|
+ else if(strcmp(status, "PERM") == 0)
|
|
+ {
|
|
+ *statp = EX_UNAVAILABLE;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ *statp = EX_PROTOCOL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ sm_free(replybuf);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return rval;
|
|
+}
|
|
+
|
|
+
|
|
+#endif /* SOCKETMAP */
|
|
Index: sendmail/sendmail/sendmail/sendmail.h
|
|
diff -u sendmail/sendmail/sendmail/sendmail.h:1.1.1.2 sendmail/sendmail/sendmail/sendmail.h:1.3
|
|
--- sendmail/sendmail.h Thu Jan 23 11:50:27 2003
|
|
+++ sendmail/sendmail.h Thu Jan 23 11:51:38 2003
|
|
@@ -1382,6 +1382,9 @@
|
|
#if LDAPMAP
|
|
MAP *sv_lmap; /* Maps for LDAP connection */
|
|
#endif /* LDAPMAP */
|
|
+#if SOCKETMAP
|
|
+ MAP *sv_socketmap; /* Maps for SOCKET connection */
|
|
+#endif /* SOCKETMAP */
|
|
#if MILTER
|
|
struct milter *sv_milter; /* milter filter name */
|
|
#endif /* MILTER */
|
|
@@ -1413,8 +1416,12 @@
|
|
#endif /* MILTER */
|
|
#define ST_QUEUE 15 /* a queue entry */
|
|
|
|
+#if SOCKETMAP
|
|
+# define ST_SOCKETMAP 16 /* List head of maps for SOCKET connection */
|
|
+#endif /* SOCKETMAP */
|
|
+
|
|
/* This entry must be last */
|
|
-#define ST_MCI 16 /* mailer connection info (offset) */
|
|
+#define ST_MCI 17 /* mailer connection info (offset) */
|
|
|
|
#define s_class s_value.sv_class
|
|
#define s_address s_value.sv_addr
|
|
@@ -1432,6 +1439,9 @@
|
|
#if LDAPMAP
|
|
# define s_lmap s_value.sv_lmap
|
|
#endif /* LDAPMAP */
|
|
+#if SOCKETMAP
|
|
+# define s_socketmap s_value.sv_socketmap
|
|
+#endif /* SOCKETMAP */
|
|
#if MILTER
|
|
# define s_milter s_value.sv_milter
|
|
#endif /* MILTER */
|
|
Index: sendmail/sendmail/sendmail/stab.c
|
|
diff -u sendmail/sendmail/sendmail/stab.c:1.1.1.1 sendmail/sendmail/sendmail/stab.c:1.2
|
|
--- sendmail/stab.c Fri Oct 11 14:44:04 2002
|
|
+++ sendmail/stab.c Wed Jan 22 18:57:22 2003
|
|
@@ -173,6 +173,12 @@
|
|
len = sizeof s->s_quegrp;
|
|
break;
|
|
|
|
+#if SOCKETMAP
|
|
+ case ST_SOCKETMAP:
|
|
+ len = sizeof s->s_socketmap;
|
|
+ break;
|
|
+#endif /* SOCKETMAP */
|
|
+
|
|
default:
|
|
/*
|
|
** Each mailer has its own MCI stab entry:
|